#include <bits/stdc++.h>
using namespace std;
const int N = 400010, INF = (int)1e9, mod = (int)1e9 + 7;
int n, m, cntStep;
vector<pair<int, int> > G[N];
vector<vector<int> > Components;
vector<pair<int, pair<int, int> > > e;
int low[N], num[N], del[N], par[N];
stack<int> st;
int dir[N << 1], newDir[N << 1], pos[N], a[N];
vector<pair<int, int> > tree[N];
void dfs(int u, int p) {
  low[u] = num[u] = ++cntStep;
  st.push(u);
  for (pair<int, int> cur : G[u]) {
    int v = cur.second;
    if (v == p) continue;
    if (num[v])
      low[u] = min(low[u], num[v]);
    else
      par[v] = u, dfs(v, u), low[u] = min(low[u], low[v]);
  }
  if (low[u] == num[u]) {
    int v = 0;
    Components.push_back(vector<int>());
    do {
      v = st.top();
      st.pop();
      del[v] = 1;
      Components.back().push_back(v);
      pos[v] = Components.size();
    } while (v != u);
  }
}
int dp[N], tot[N];
void optimize(int u, int p, int val) {
  dp[u] = a[u];
  tot[u] = a[u];
  for (pair<int, int> cur : tree[u]) {
    int v = cur.second, id = cur.first;
    if (v == p) continue;
    optimize(v, u, val);
    if (dp[v] >= val)
      newDir[id] = 1, newDir[id ^ 1] = 2, tot[u] += tot[v], dp[u] += tot[v];
    else
      newDir[id] = 2, newDir[id ^ 1] = 1;
  }
  for (pair<int, int> cur : tree[u]) {
    int v = cur.second, id = cur.first;
    if (v == p) continue;
    if (newDir[id] == 2) dp[u] = min(dp[u], dp[v] + tot[u]);
  }
}
bool check(int val) {
  memset(newDir, 0, sizeof newDir);
  memset(dp, 0, sizeof dp);
  memset(tot, 0, sizeof tot);
  for (int i = (int)(0); i <= (int)(2 * m); i++) newDir[i] = dir[i];
  optimize(1, 0, val);
  return dp[1] >= val;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v;
    cin >> u >> v;
    G[u].push_back(pair<int, int>(2 * i, v));
    G[v].push_back(pair<int, int>(2 * i + 1, u));
    e.push_back(pair<int, pair<int, int> >(2 * i, pair<int, int>(u, v)));
  }
  par[1] = 0;
  dfs(1, 0);
  for (int i = 0; i < Components.size(); i++) {
    a[i + 1] = Components[i].size();
  }
  for (int i = (int)(0); i <= (int)(e.size() - 1); i++) {
    int id = e[i].first, u = e[i].second.first, v = e[i].second.second;
    if (pos[u] == pos[v]) {
      if (u == par[v])
        dir[id] = 1, dir[id ^ 1] = 2;
      else if (v == par[u])
        dir[id] = 2, dir[id ^ 1] = 1;
      else if (num[v] > num[u])
        dir[id] = 2, dir[id ^ 1] = 1;
      else
        dir[id] = 1, dir[id ^ 1] = 2;
    } else
      tree[pos[u]].push_back(pair<int, int>(id, pos[v])),
          tree[pos[v]].push_back(pair<int, int>(id ^ 1, pos[u]));
  }
  int l = 0, r = n;
  while (l != r) {
    int mid = (l + r + 1) >> 1;
    if (check(mid))
      l = mid;
    else
      r = mid - 1;
  }
  check(l);
  cout << l << endl;
  for (int i = (int)(0); i <= (int)(2 * m); i++) dir[i] = newDir[i];
  for (int i = (int)(0); i <= (int)(e.size() - 1); i++) {
    int id = e[i].first, u = e[i].second.first, v = e[i].second.second;
    if (dir[id] <= 1)
      cout << u << ' ' << v << endl;
    else
      cout << v << ' ' << u << endl;
  }
}
