- 就是求二分图的关键边
- 一条边是二分图的关键边当且仅当:这条边满流&&边的两端不在一个scc中
- 一条边是二分图的可行边当且仅当:这条边满流||边的两端在一个scc中
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int inf=1e9;
const int N=2e4;
const int M=2e5;
struct node{int x,y,v,n,id;}e[M<<1],E[M<<1];
struct QWQ{int x,y;}q[M],ans[M];
int lin[M<<1],LIN[M<<1],dfn[N],low[N],inv[N],c[N],d[N],v[M<<1],scc,tot,S,T,LEN,len=1,n,m,x,y;
inline int read(){
int num=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))num=num*10+ch-'0',ch=getchar();
return num;
}
inline void Print(int x){if(x>9)Print(x/10);putchar(x%10+'0');}
void LK(int x,int y,int v,node *e,int *lin,int &len){
e[++len].y=y,e[len].x=x,e[len].v=v,e[len].n=lin[x],lin[x]=len;
}
void add(int x,int y,int v){
LK(x,y,v,e,lin,len),LK(y,x,0,e,lin,len);
}
void DFS(int x){
for(int i=LIN[x];i;i=E[i].n){
int y=E[i].y;
if(v[y]!=-1)continue;
v[y]=v[x]^1;DFS(y);
}
}
bool bfs(){
queue<int> q;
memset(d,0,sizeof(d));
d[S]=1,q.push(S);
while(q.size()){
int x=q.front();q.pop();
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(d[y]||!e[i].v)continue;
d[y]=d[x]+1;q.push(y);
}
}return d[T]>0;
}
int dfs(int x,int minf){
if(x==T)return minf;
int flow=0,sum=0;
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(d[y]!=d[x]+1||!e[i].v)continue;
flow=dfs(y,min(minf,e[i].v));
if(!flow)d[y]=0;
sum+=flow,minf-=flow,e[i].v-=flow,e[i^1].v+=flow;
if(!minf)return sum;
}return sum;
}
stack<int> SS;
void tarjan(int x){
dfn[x]=low[x]=++tot;inv[x]=1;SS.push(x);
for(int i=lin[x];i;i=e[i].n){
int y=e[i].y;
if(!e[i].v)continue;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}else if(inv[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
int now=-1;scc++;
while(now!=x){
now=SS.top();SS.pop();
c[now]=scc;
inv[now]=0;
}
}
}
bool cmp(QWQ a,QWQ b){return a.x==b.x&&a.y<b.y||a.x<b.x;}
int main()
{
//freopen("a.in","r",stdin);
n=read(),m=read(); S=0,T=n+1;
rep(i,1,m){
x=read(),y=read();
q[i].x=x,q[i].y=y;
LK(x,y,0,E,LIN,LEN),LK(y,x,0,E,LIN,LEN);
}
memset(v,-1,sizeof(v));
rep(i,1,n)if(v[i]==-1)v[i]=0,DFS(i);
rep(i,1,m){
x=q[i].x,y=q[i].y;
if(v[x])add(y,x,1);
else add(x,y,1);
}
rep(i,1,n){
if(v[i])add(i,T,1);
else add(S,i,1);
}
while(bfs())dfs(S,inf);
rep(i,1,n)if(!dfn[i])tarjan(i);
tot=0;
for(int i=2;i<=len;i+=2){
x=e[i].x,y=e[i].y;
if(x==0||y==0||x==T||y==T)continue;
if(e[i].v==0&&c[x]!=c[y])ans[++tot].x=min(x,y),ans[tot].y=max(x,y);
}
cout<<tot<<"\n";
sort(ans+1,ans+tot+1,cmp);
rep(i,1,tot)cout<<ans[i].x<<" "<<ans[i].y<<"\n";
return 0;
}