#include <bits/stdc++.h>
using namespace std;
namespace A {
bool debug_flag = false;
vector<pair<int, int> > in;
vector<int> bridges;
int timer;
vector<char> used;
vector<int> tin;
vector<int> fup;
vector<vector<pair<int, int> > > g;
void bridges_dfs(int v, int p = -1) {
  used[v] = true;
  tin[v] = fup[v] = timer++;
  for (auto& it : g[v]) {
    int& to = it.first;
    int& i = it.second;
    if (to == p) continue;
    if (used[to])
      fup[v] = min(fup[v], tin[to]);
    else {
      bridges_dfs(to, v);
      fup[v] = min(fup[v], fup[to]);
      if (fup[to] > tin[v]) bridges.push_back(i);
    }
  }
}
void find_bridges(int n) {
  timer = 0;
  used.clear();
  used.resize(n, false);
  tin.resize(n);
  fup.resize(n);
  for (int i = 0; i < n; ++i)
    if (!used[i]) bridges_dfs(i);
  sort(bridges.begin(), bridges.end());
}
vector<int> dsu_base;
vector<int> dsu_size;
void init(int n) {
  dsu_size.clear();
  dsu_size.resize(n, 1);
  dsu_base.resize(n);
  for (int i = 0; i < n; ++i) dsu_base[i] = i;
}
int get(int i) { return dsu_base[i] == i ? i : dsu_base[i] = get(dsu_base[i]); }
void link(int a, int b) {
  a = get(a);
  b = get(b);
  if (a == b) return;
  if (dsu_size[a] > dsu_size[b]) swap(a, b);
  dsu_base[a] = b;
  dsu_size[b] += dsu_size[a];
}
vector<pair<int, int> > ans;
int ans_dfs(int v) {
  used[v] = true;
  int sz = 1;
  for (auto& it : g[v]) {
    int& to = it.first;
    int& i = it.second;
    if (ans[i].first == -1) ans[i] = {v, to};
    if (!used[to]) {
      sz += ans_dfs(to);
    }
  }
  return sz;
}
struct rrr {
  int base_from;
  int base_to;
  int to;
  int i;
  rrr(int _bfrom, int _bto, int _to, int ind)
      : base_from(_bfrom), base_to(_bto), to(_to), i(ind){};
};
vector<vector<rrr> > gg;
void gg_dfs(int v) {
  used[v] = true;
  for (rrr& it : gg[v]) {
    if (ans[it.i].first == -1) ans[it.i] = {it.base_to, it.base_from};
    if (!used[it.to]) {
      gg_dfs(it.to);
    }
  }
}
int fill_ans(int n) {
  used.clear();
  used.resize(n, false);
  int mx_size = 0;
  int mx_ind = -1;
  for (int i = 0; i < n; ++i)
    if (!used[i]) {
      int sz = ans_dfs(i);
      if (sz > mx_size) mx_size = sz, mx_ind = i;
    }
  gg.resize(n);
  for (int& i : bridges) {
    int a = in[i].first;
    int b = in[i].second;
    gg[get(a)].push_back(rrr(a, b, get(b), i));
    gg[get(b)].push_back(rrr(b, a, get(a), i));
  }
  used.clear();
  used.resize(n, false);
  gg_dfs(get(mx_ind));
  return mx_size;
}
void solve() {
  int n, m;
  scanf("%d%d", &n, &m);
  g.resize(n);
  in.resize(m);
  for (auto& it : in)
    scanf("%d%d", &it.first, &it.second), it.first--, it.second--;
  for (int i = 0; i < m; ++i)
    g[in[i].first].push_back({in[i].second, i}),
        g[in[i].second].push_back({in[i].first, i});
  find_bridges(n);
  for (int i = 0; i < n; ++i) g[i].clear();
  init(n);
  for (int i = 0, j = 0; i < m; ++i) {
    if (j < (int)bridges.size() && bridges[j] < i) ++j;
    if (j < (int)bridges.size() && i == bridges[j]) continue;
    int& a = in[i].first;
    int& b = in[i].second;
    link(a, b);
    g[a].push_back({b, i}), g[b].push_back({a, i});
  }
  ans.resize(m, {-1, -1});
  printf("%d\n", fill_ans(n));
  for (auto& it : ans) printf("%d %d\n", it.first + 1, it.second + 1);
}
}  // namespace A
int main() {
  A::solve();
  return 0;
}
