#include<stdio.h>
#define infile "cuplaj.in"
#define outfile "cuplaj.out"
#define nmax (20*1000+5)
#define mmax (nmax+100*1000+1)
#define inf ~(1<<31)
struct lista
{
int n,p,f; //nodul pozitia si fluxul folosit pe acest arc
} l[mmax],lt[mmax]; //lista pt graful normal si pt graful transpus
int viz[nmax]; //vector pt vizite
int c[nmax]; //coada
int p[nmax],pt[nmax]; //pozitiile din lista pt graful normal si pt cel transpus
int le,ri; //lungimea celor doua grupuri de noduri
int n,m; //numarul de noduri respectiv muchii
int st,fi; //cele doua noduri pe care le adaugam a.i. sa avem o retea
int flux; //fluxul maxim din cuplaj
int modul(int x)
{
if(x<0) return (-1)*x;
return x;
}
//adauga arcul (x,y) in lista
void add(struct lista l[mmax], int p[nmax], int m, int x, int y)
{
l[m].n=y; l[m].p=p[x]; p[x]=m;
}
void citire()
{
int i,x,y;
scanf("%d %d %d\n",&le,&ri,&m); //nuymarul nodurilor din fiecare grupa, si numarul de muchii dintre noduri
for(i=1;i<=m;i++) //fiecare muchie in parte
{
scanf("%d %d\n",&x,&y);
y+=le; //numerotarea nodurilor din grupa 2 incepe de la l
add(l,p,i,x,y); //graful normal
add(lt,pt,i,y,x); //graful transpus
}
n=le+ri+2; //numarul total de noduri
}
//transformam graful intr-o retea de transport
void initializare()
{
int i;
st=le+ri+1; fi=st+1; //nuymarul de ordine al celor doua noduri (start si final)
for(i=1;i<=le;i++) //trebuie sa adaugam arc de la nodul de start la toate nodurile din grupa l
{
++m;
add(l,p,m,st,i); //adaugam in graful normal
add(lt,pt,m,i,st); //adaugam in graful transpus
}
for(i=1;i<=ri;i++)//trebuie sa adaugam arc de la fiecare nod din grupa a 2-a la nodul final
{
++m;
add(l,p,m,le+i,fi); //graful normal
add(lt,p,m,fi,le+i); //graful transpus
}
}
//modifica fluxul pentru un arc din lista
void modifica_flux(struct lista l[mmax], int p[nmax], int x, int y, int f)
{
int ul=p[x]; //pozitia copilului
while(ul) //cat timp are copil
{
if(l[ul].n==y) { l[ul].f=f; break; } //am gasit nodul..modific fluxul
ul=l[ul].p; //frasu
}
}
//incercam sa atingem nodul final....din nodul x
int bfs(int x)
{
int cs,cd; //pozitiile coade
int ul;
c[cs=cd=1]=x; viz[x]=1; //initializam coada
while(cs<=cd) //cat timp avem elemente in coada
{
int x=c[cs]; //nodul caruia trebuie sa ii cautam copii
for(ul=p[x];ul;ul=l[ul].p) //trecem la toti copii lui x
if(!viz[l[ul].n]&&!l[ul].f) //daca nodul nu a mai fost vizitat, si daca arcul nu este saturat
{
c[++cd]=l[ul].n; //il adaugam in coada
viz[l[ul].n]=x; //il marcam ca vizitat, si ca venim de la x
if(l[ul].n==fi) return 1; //am atins nodul final
}
for(ul=pt[x];ul;ul=lt[ul].p) //copii din graful transpus
if(!viz[lt[ul].n]&<[ul].f) //daca nodul nu a fost vizitat, si daca avem flux (parcurgerea este DESTINATIE-SRUSA)
{
c[++cd]=lt[ul].n; //adaugam in coada
viz[lt[ul].n]=-x; //il marcam vizitat...si cu minus pt k este in sens invers
}
cs++; //inaintam in coada
}
return 0; //daca am ajuns aici, inseamna k nu am atins nodul final
}
void calculeaza_flux()
{
int s[nmax]; //stiva in care refacem lantul de ameliorare
int i; //fluxul oricarui lant este egal cu 1
while(bfs(st)) //cat timp atingem nodul final
{
s[s[0]=1]=fi; //initial avem nodul final
do
{
s[++s[0]]=modul(viz[s[s[0]-1]]); //adaugam in lant pe cel de la care vine
if(viz[s[s[0]-1]]>0) //lantul se parcurge in mod normal
{
modifica_flux(l,p,s[s[0]],s[s[0]-1],1); //salvam fluxul pe lant
modifica_flux(lt,pt,s[s[0]-1],s[s[0]],1); //salvam fluxul pe lant in cel transpus
}
else //inseamna k lantul se parcurge in sens invers
{
modifica_flux(l,p,s[s[0]-1],s[s[0]],0); //salvam fluxul pe lant
modifica_flux(lt,pt,s[s[0]],s[s[0]-1],0); //salvam fluxul pe lantul transpus
}
}
while(s[s[0]]!=st); //pana nu am adaugat nodul initial..refacem lantul
flux++; //crestem fluxu;
for(i=1;i<=n;i++) viz[i]=0; //golim vectorul viz
}
}
void afisare()
{
int i,ul;
printf("%d\n",flux); //afisem fluxul maxim
for(i=1;i<=le;i++) //luam fiecare nod din primul grup
{
ul=p[i]; //ii luam pozitia din lista
while(ul)
{
if(l[ul].f==1) { printf("%d %d\n",i,l[ul].n-le); break; }//afisem muchia si oprim
ul=l[ul].p; //frasu
}
}
}
int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);
citire(); //citim graful
initializare(); //transformam graful in retea de transport
calculeaza_flux(); //facem reteaua pentru flux maxim (adica legaturile ...cuplajul)
afisare(); //afisem
fclose(stdin);
fclose(stdout);
return 0;
}