#include <bits/stdc++.h>
using namespace std;
int n, m;
int t, birth[400055], low[400055];
int cmp[400055];
int k;
vector<int> g[400055];
stack<int> sta;
set<pair<int, int> > reserve, should;
int tot[400055];
struct edge {
  int to;
  int u;
  int v;
};
vector<edge> ng[400055];
void tarjan(int v, int par = -1) {
  birth[v] = low[v] = ++t;
  sta.push(v);
  int from = -1;
  for (auto u : g[v]) {
    if (u == par) continue;
    if (!birth[u]) {
      reserve.insert(pair<int, int>(v, u));
      tarjan(u, v);
      if (low[v] > low[u]) {
        from = u;
        low[v] = low[u];
      }
    } else if (low[v] > birth[u]) {
      reserve.insert(pair<int, int>(v, u));
      from = u;
      low[v] = birth[u];
    }
  }
  if (birth[v] == low[v]) {
    int u;
    k++;
    set<int> appear;
    do {
      u = sta.top();
      sta.pop();
      cmp[u] = k;
      tot[k]++;
    } while (u != v);
  }
}
int r[400055];
int dir[400055];
bool diu;
void dfs(int v, int par, int cost, int actualu = -1, int actualv = -1) {
  for (auto e : ng[v]) {
    if (e.to == par) continue;
    dfs(e.to, v, cost, e.u, e.v);
  }
  if (r[v] >= cost && par != -1) {
    dir[v] = 1;
    r[par] += r[v];
    if (diu) should.insert(pair<int, int>(actualu, actualv));
  } else if (r[v] < cost && par != -1) {
    if (diu) should.insert(pair<int, int>(actualv, actualu));
  }
}
void rdfs(int v, int par) {
  if (dir[v] == 0) {
    r[v] += r[par];
  }
  for (auto e : ng[v]) {
    if (e.to == par) continue;
    rdfs(e.to, v);
  }
}
bool C(int x) {
  should.clear();
  memset(dir, 0, sizeof(dir));
  for (int i = 1; i <= k; i++) r[i] = tot[i];
  dfs(1, -1, x);
  rdfs(1, -1);
  for (int i = 1; i <= k; i++)
    if (r[i] < x) return false;
  return true;
}
int main() {
  scanf("%d %d", &n, &m);
  int x, y;
  vector<pair<int, int> > es;
  while (m--) {
    scanf("%d %d", &x, &y);
    x--, y--;
    g[x].push_back(y);
    g[y].push_back(x);
    es.push_back(pair<int, int>(x, y));
  }
  tarjan(0);
  vector<pair<int, int> > vec;
  for (auto p : reserve)
    if (cmp[p.first] != cmp[p.second]) vec.push_back(p);
  for (auto p : vec) reserve.erase(p);
  for (int v = 0; v < n; v++) {
    for (auto u : g[v]) {
      if (cmp[v] != cmp[u]) {
        ng[cmp[v]].push_back((edge){cmp[u], v, u});
      }
    }
  }
  int lb = 0, ub = n + 1;
  while (ub - lb > 1) {
    int mid = (ub + lb) >> 1;
    if (C(mid))
      lb = mid;
    else
      ub = mid;
  }
  diu = true;
  C(lb);
  printf("%d\n", lb);
  for (auto p : es) {
    if (reserve.find(p) != reserve.end() || should.find(p) != should.end()) {
      printf("%d %d\n", p.first + 1, p.second + 1);
      continue;
    }
    swap(p.first, p.second);
    printf("%d %d\n", p.first + 1, p.second + 1);
  }
  return 0;
}
