#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10,M=5e6+10,inf=1<<30;
int n,m;
struct DINIC{
int Next[M],d[N],head[N],ver[M],edge[M],tot,S,T;
queue<int> q;
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot;
}
void build(){
tot=1,S=N-2,T=N-1;int x,y;
while(scanf("%d%d",&x,&y)&&x>0)add(x,y,1);
for(int i=1;i<=n;++i)add(S,i,1);
for(int i=n+1;i<=m;++i)add(i,T,1);
}
bool bfs(){
memset(d,0,sizeof d);
while(q.size())q.pop();
q.push(S);d[S]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=Next[i])
if(edge[i]&&!d[ver[i]]){
q.push(ver[i]);
d[ver[i]]=d[x]+1;
if(ver[i]==T)return 1;
}
}
return 0;
}
int find(int x,int flow){
if(x==T)return flow;
int rest=flow,k;
for(int i=head[x];i&&rest;i=Next[i])
if(edge[i]&&d[ver[i]]==d[x]+1){
k=find(ver[i],min(rest,edge[i]));
if(!k)d[ver[i]]=0;
edge[i]-=k;
edge[i^1]+=k;
rest-=k;
}
return flow-rest;
}
int dinic(){
int flow=0,maxflow=0;
while(bfs())
while(flow=find(S,inf))maxflow+=flow;
return maxflow;
}
void solve(){
for(int i=1;i<=n;++i){
for(int j=head[i];j;j=Next[j]){
if(edge[j]==0&&ver[j]!=S)printf("%d %d\n",i,ver[j]);
}
}
}
}G;
int main(){
cin>>n>>m;
G.build();
cout<<G.dinic()<<endl;
G.solve();
}