/**
未盖点:不与任何匹配边邻接的点
匹配点:匹配边相连的顶点
匹配:两两没有公共点的边集
交替路:从未盖点出发,依次经过非匹配边,匹配边,非匹配边....所得到的路径
增广路:交替路的终点是一个未盖点。
增广路的长度为奇数,因为非匹配边比匹配边多一条。
一个匹配是最大匹配的充要条件是不存在增广路。
匈牙利算法,即不断增广,直到不能继续增广,达到最大匹配。
*/
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXV=550; //顶点数
bool G[MAXV][MAXV],vis[MAXV]; //用邻接表存图,vis标记
int match[MAXV]; //保存X,Y匹配关系
int k,m,n;
int find_AP(int u){ //从Xu出发找增广路
for(int i=1;i<=n;i++){ //遍历Yi
if(!vis[i]&&G[u][i]){ //如果有路径可达且
vis[i]=1;
if(!match[i]||find_AP(match[i])){
//如果Yi是未盖点或Yi非未盖点即Yi的匹配Xc还能增广
match[i]=u; //match[i]记录Yi与Xu匹配
return true; //返回找到一条增广路
}
}
}
return false;
}
int main(){
int ans,a,b;
while(scanf("%d",&k)!=EOF&&k){
ans=0;
memset(match,0,sizeof(match));
memset(G,0,sizeof(G));
scanf("%d%d",&m,&n);
for(int i=0;i<k;i++){
scanf("%d%d",&a,&b);
G[a][b]=1; //记录a--b间有路径
}
for(int i=1;i<=m;i++){ //用X向Y增广
memset(vis,0,sizeof(vis));//清空标记
if(find_AP(i)) //找Xi的增广路,找到后变量增加1,
//直到不能增广,说明已经是最大匹配
ans++;
}
printf("%d\n",ans);
}
return 0;
}