#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std ;
const int MAXN=1000;
int uN,vN;
int g[MAXN][MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u){
for(int v=1;v<=vN;v++)
if(g[u][v]&&!used[v]){
used[v]=true;
if(linker[v]==-1||dfs(linker[v])){
linker[v]=u;
return true;
}
}
return false;
}
int hungary(){
int res=0;
memset(linker,-1,sizeof(linker));
for(int u=1;u<=uN;u++){
memset(used,0,sizeof(used));
if(dfs(u)){
res++;
}
}
return res;
}
int main(){
int k , u , v ;
while( scanf("%d" , & k ) && k ){
scanf("%d%d" , & uN , & vN ) ;
memset( g , 0 , sizeof( g )) ;
while( k -- ){
scanf("%d%d" , & u , & v ) ;
g[u][v] = 1;
}
printf("%d\n" , hungary() ) ;
}
return 0 ;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std ;
const int MAXN=500 + 10;
const int INF=1<<28;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP(){
queue<int>Q;
dis=INF;
memset(dx,-1,sizeof(dx));
memset(dy,-1,sizeof(dy));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1){
Q.push(i);
dx[i]=0;
}
while(!Q.empty()){
int u=Q.front();
Q.pop();
if(dx[u]>dis) break;
for(int v=0;v<Ny;v++)
if(g[u][v]&&dy[v]==-1){
dy[v]=dx[u]+1;
if(My[v]==-1) dis=dy[v];
else
{
dx[My[v]]=dy[v]+1;
Q.push(My[v]);
}
}
}
return dis!=INF;
}
bool DFS(int u){
for(int v=0;v<Ny;v++)
if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1){
vst[v]=1;
if(My[v]!=-1&&dy[v]==dis) continue;
if(My[v]==-1||DFS(My[v])){
My[v]=u;
Mx[u]=v;
return 1;
}
}
return 0;
}
int MaxMatch(){
int res=0;
memset(Mx,-1,sizeof(Mx));
memset(My,-1,sizeof(My));
while(searchP()){
memset(vst,0,sizeof(vst));
for(int i=0;i<Nx;i++)
if(Mx[i]==-1&&DFS(i))
res++;
}
return res;
}
int main(){
int k , u , v ;
while( scanf("%d" , & k ) && k ){
scanf("%d%d" , & Nx , & Ny ) ;
memset( g , 0 , sizeof( g )) ;
while( k -- ){
scanf("%d%d" , & u , & v ) ;
g[u - 1][v - 1] = 1;
}
printf("%d\n" , MaxMatch() ) ;
}
return 0 ;
}