#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
char viz[nmax]; //vector pt vizite
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 m; //numarul de muchii
int st,fi; //cele doua noduri pe care le adaugam a.i. sa avem o retea
int flux; //fluxul maxim din cuplaj
//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
}
}
//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
}
}
//apelam un nod (cu fluxul f)....si returnam fluxul nefolosit de nod
int dfs(int x, int f)
{
viz[x]=1; //marcam ca vizitat nodul x
if(x==fi) { flux+=f; return 0; } //am atins finalul...salvam fluxul si returnam 0
int ul,c;
for(ul=p[x];ul&&f;ul=l[ul].p) //parcurgem copii lui x
if(!viz[l[ul].n]&&!l[ul].f) //daca n-am mai vizitat nodul, si daca arcul nu este satura (fluxul este 0)
{
c=dfs(l[ul].n,1); //apelam nodul cu fluxul 1
viz[l[ul].n]=0; //devizitam nodul
if(!c) //daca nu a returna flux...deci a folosit tot
{
l[ul].f=1; //saturam arcul
modifica_flux(lt,pt,l[ul].n,x,1); //modificam fluxul si in lista pt graful transpus
f-=1; //scadem ca am folosit din flux
}
}
for(ul=pt[x];ul&&f;ul=lt[ul].p) //parcurgem copii lui x in graful transpus (deci destinatie-sursa)
if(!viz[lt[ul].n]&<[ul].f) //daca nodul nu a mai fost vizitat si daca avem flux (aici trebuie sa avem flux)
{
c=dfs(lt[ul].n,1); //apelam nodul cu fluxul 1...
viz[lt[ul].n]=0; //devizitam nodul
if(!c) //daca nu a returnat flux....deci a folosit tot
{
lt[ul].f=0; //scadem fluxul
modifica_flux(l,p,lt[ul].n,x,0); //modificam fluxul si in graful normal
f-=1; //scadem k am folosit 1 din flux
}
}
return f; //returnam fluxul nefolosit
}
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
dfs(st,inf); //parcurgem reteaua din nodul de start cu flux infinit...si aflam fluxul total
afisare(); //afisem
fclose(stdin);
fclose(stdout);
return 0;
}