#include <bits/stdc++.h>   using namespace std;   const int MAXN = 5004;   const int MAXNN = MAXN * 2 + 10;   const int INF = 0x3f3f3f3f;   struct Edge {     int u, v, f, cap;     Edge() { f = 0; }     Edge(int uu, int vv, int cc) : u(uu), v(vv), f(0), cap(cc) {}     inline int other(int w) { return w == u ? v : u; }     inline int flow(int from) { return from == u ? cap - f : f; }     inline void augment(int from, int val) {       if (from == u)         f += val;       else         f -= val;     }   };   struct Dinic {     int N;     vector<int> par, L, pt, eIdx;     vector<Edge> E;     vector<vector<int>> a;     Dinic(int n) : N(n), par(n), L(n), pt(n), eIdx(n), a(n) {}     Dinic() : N(0) {}     void addEdge(int u, int v, int c) {       if (u != v) {         E.emplace_back(u, v, c);         a[u].push_back(E.size() - 1);         a[v].push_back(E.size() - 1);       }     }     void clearFlow() {       for (Edge &e : E) e.f = 0;     }     bool BFS(int source, int target) {       const int INF = 0x3f3f3f3f;       queue<int> Q;       fill(L.begin(), L.end(), INF);       L[source] = 0;       Q.push(source);       while (Q.size()) {         int u = Q.front();         Q.pop();         for (int ei : a[u]) {           Edge &e = E[ei];           int v = e.other(u);           if (L[v] > L[u] + 1 && e.flow(u)) {             L[v] = L[u] + 1;             if (v == target) return true;             Q.push(v);           }         }       }       return false;     }     int DFS(int source, int target) {       stack<int> S;       int ans = 0;       S.push(source);       while (S.size()) {         int u = S.top();         if (u == target) {           int f = 1e9, bottleneck = -1;           for (int cur = target; cur != source; cur = par[cur])             f = min(f, E[eIdx[cur]].flow(par[cur]));           for (int cur = target; cur != source; cur = par[cur]) {             Edge &e = E[eIdx[cur]];             e.augment(par[cur], f);             if (!e.flow(par[cur])) bottleneck = par[cur];           }           ans += f;           while (S.top() != bottleneck) S.pop();         } else {           if (pt[u]) {             int &i = pt[u];             while (--i >= 0) {               int ei = a[u][i];               Edge &e = E[ei];               int v = e.other(u);               if (pt[v] > 0 && L[u] + 1 == L[v] && e.flow(u)) {                 par[v] = u;                 eIdx[v] = ei;                 S.push(v);                 break;               }             }           }           if (S.top() == u) {             pt[u] = 0;             S.pop();           }         }       }       return ans;     }     int maxFlow(int source, int target) {       int mf = 0, f;       clearFlow();       while (BFS(source, target)) {         for (int i = 0; i < N; ++i) pt[i] = (int)a[i].size();         while (pt[source]) {           f = DFS(source, target);           if (!f) break;           mf += f;         }       }       return mf;     }   };   bool vis[MAXNN];   int n, m, S, T;   inline void init(Dinic &F, int val) {     for (int ei : F.a[T]) {       F.E[ei].cap = val;     }   }   void bs(Dinic &F) {     int hi = n, lo = 0, ans = 0, mid;     while (hi >= lo) {       mid = (hi + lo) >> 1;       init(F, mid);       if (F.maxFlow(S, T) == m) {         ans = mid;         hi = mid - 1;       } else {         lo = mid + 1;       }     }     init(F, ans);     F.maxFlow(S, T);     printf( %d n , ans);     for (int i = 1, from = -1, to = -1; i <= m; ++i) {       for (int ei : F.a[i]) {         Edge &e = F.E[ei];         if (e.other(i) == S) continue;         if (e.flow(i))           to = e.other(i);         else           from = e.other(i);       }       printf( %d %d n , from - m, to - m);     }   }   int main() {     scanf( %d%d , &n, &m);     S = 0;     T = n + m + 1;     Dinic F(T + 1);     for (int i = 1, x, y; i <= m; ++i) {       scanf( %d%d , &x, &y);       F.addEdge(i, m + x, 1);       F.addEdge(i, m + y, 1);       F.addEdge(S, i, 1);     }     for (int i = 1; i <= n; ++i) F.addEdge(m + i, T, MAXN);     bs(F);     return 0;   }