#include <bits/stdc++.h>
using namespace std;
char *p1, *p2, buf[100000];
int rd() {
  int x = 0, f = 1;
  char c =
      (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
           ? EOF
           : *p1++);
  while (c < 48) {
    if (c == '-') f = -1;
    c = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++);
  }
  while (c > 47) {
    x = (((x << 2) + x) << 1) + (c ^ 48),
    c = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
             ? EOF
             : *p1++);
  }
  return x * f;
}
int dep[400010], low[400010], cnt, st[400010], top, blg[400010];
bool vis[400010], ins[400010];
vector<int> Sc[400010];
int head[400010], to[400010 << 1], nxt[400010 << 1], tot;
inline void add(int x, int y) {
  to[++tot] = y;
  nxt[tot] = head[x];
  head[x] = tot;
}
void tarjan(int p, int fa) {
  dep[p] = low[p] = ++cnt;
  st[++top] = p, vis[p] = ins[p] = true;
  for (int i = head[p]; i; i = nxt[i]) {
    if (to[i] != fa) {
      if (!vis[to[i]]) {
        tarjan(to[i], p);
        low[p] = min(low[p], low[to[i]]);
      } else if (ins[to[i]]) {
        low[p] = min(low[p], dep[to[i]]);
      }
    }
  }
  if (dep[p] == low[p]) {
    blg[0]++;
    int t;
    do {
      t = st[top--];
      ins[t] = false;
      blg[t] = blg[0];
      Sc[blg[0]].push_back(t);
    } while (t != p);
  }
}
int head1[400010], to1[400010 << 1], nxt1[400010 << 1], tot1, v[400010];
inline void add1(int x, int y) {
  to1[++tot1] = y;
  nxt1[tot1] = head1[x];
  head1[x] = tot1;
}
struct Edge {
  int x, y;
} e[400010];
map<pair<int, int>, bool> MP;
struct Bian {
  int head[400010], to[400010 << 1], nxt[400010 << 1], tot;
  inline void add(int x, int y) {
    to[++tot] = y;
    nxt[tot] = head[x];
    head[x] = tot;
  }
} G, G1;
int value, mdlv[400010], n, m;
map<pair<int, int>, int> edgere, Out;
bool ans_check = true;
int du[400010];
void dfs(int p, int fa) {
  for (int i = head1[p]; i; i = nxt1[i]) {
    if (to1[i] != fa) {
      dfs(to1[i], p);
    }
  }
  if (p != 1) {
    if (mdlv[p] < value) {
      if (value == 4) {
      }
      G.add(fa, p);
      du[p]++;
    } else {
      if (value == 4) {
      }
      G.add(p, fa);
      du[fa]++;
      mdlv[fa] += mdlv[p];
    }
  }
}
int f[400010];
queue<int> q;
bool check(int x) {
  memset(G.head, 0, sizeof G.head), G.tot = 0;
  value = x;
  for (int i = 1; i <= blg[0]; i++) {
    mdlv[i] = v[i];
  }
  memset(du, 0, sizeof du);
  dfs(1, 1);
  for (int i = 1; i <= blg[0]; i++) {
    f[i] = v[i];
    if (!du[i]) {
      q.push(i);
    }
  }
  while (!q.empty()) {
    int y = q.front();
    q.pop();
    for (int i = G.head[y]; i; i = G.nxt[i]) {
      f[G.to[i]] += f[y];
      du[G.to[i]]--;
      if (!du[G.to[i]]) {
        q.push(G.to[i]);
      }
    }
  }
  for (int i = 1; i <= blg[0]; i++) {
    if (f[i] < x) {
      return false;
    }
  }
  return true;
}
int ansx[400010], ansy[400010];
void outputdfs(int p, int fa) {
  for (int i = head1[p]; i; i = nxt1[i]) {
    if (to1[i] != fa) {
      outputdfs(to1[i], p);
    }
  }
  if (p != 1) {
    int id = edgere[make_pair(p, fa)];
    int x = e[id].x, y = e[id].y;
    if (blg[x] != p) {
      swap(x, y);
    }
    if (mdlv[p] < value) {
      ansx[0]++;
      ansx[ansx[0]] = x, ansy[ansx[0]] = y;
    } else {
      mdlv[fa] += mdlv[p];
      ansx[0]++;
      ansx[ansx[0]] = y, ansy[ansx[0]] = x;
    }
  }
}
void output(int x) {
  memset(G.head, 0, sizeof G.head), G.tot = 0;
  value = x;
  for (int i = 1; i <= n; i++) {
    mdlv[i] = v[i];
  }
  memset(du, 0, sizeof du);
  outputdfs(1, 1);
}
bool td[400010];
map<pair<int, int>, bool> used;
void tarjan_dfs(int p, int fa) {
  td[p] = true;
  for (int i = G1.head[p]; i; i = G1.nxt[i]) {
    if (G1.to[i] != fa) {
      if (!used[make_pair(min(p, G1.to[i]), max(p, G1.to[i]))]) {
        ansx[0]++;
        ansx[ansx[0]] = p, ansy[ansx[0]] = G1.to[i];
        used[make_pair(min(p, G1.to[i]), max(p, G1.to[i]))] = 1;
      }
      if (!td[G1.to[i]]) {
        tarjan_dfs(G1.to[i], p);
      }
    }
  }
}
struct Node {
  int x, y, id;
} aaa[400010];
inline bool cmp(const Node &a, const Node &b) { return a.id < b.id; }
int main() {
  n = rd(), m = rd();
  tot = 1;
  for (int i = 1; i <= m; i++) {
    int x = rd(), y = rd();
    Out[make_pair(x, y)] = Out[make_pair(y, x)] = i;
    add(x, y), add(y, x);
    e[i].x = x, e[i].y = y;
  }
  for (int i = 1; i <= n; i++) {
    if (!vis[i]) {
      tarjan(i, 0);
    }
  }
  for (int i = 1; i <= blg[0]; i++) {
    int len = Sc[i].size();
    for (int j = 0; j < len; j++) {
      int x = Sc[i][j];
      for (int k = head[x]; k; k = nxt[k]) {
        if (blg[to[k]] == i) {
          G1.add(x, to[k]);
        }
      }
    }
    tarjan_dfs(Sc[i][0], 0);
  }
  tot1 = 1;
  for (int i = 1; i <= m; i++) {
    int x = blg[e[i].x], y = blg[e[i].y];
    if (x != y && !MP[make_pair(x, y)]) {
      MP[make_pair(x, y)] = MP[make_pair(y, x)] = true;
      add1(x, y), add1(y, x);
      edgere[make_pair(x, y)] = edgere[make_pair(y, x)] = i;
    }
  }
  for (int i = 1; i <= n; i++) {
    v[blg[i]]++;
  }
  int l = 1, r = n, re = 1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (check(mid)) {
      l = mid + 1;
      re = mid;
    } else {
      r = mid - 1;
    }
  }
  cout << re << endl;
  output(re);
  for (int i = 1; i <= ansx[0]; i++) {
    aaa[i].x = ansx[i], aaa[i].y = ansy[i],
    aaa[i].id = Out[make_pair(ansx[i], ansy[i])];
  }
  sort(aaa + 1, aaa + m + 1, cmp);
  for (int i = 1; i <= m; i++) {
    printf("%d %d\n", aaa[i].x, aaa[i].y);
  }
  return 0;
}
