#include<bits/stdc++.h>
using namespace std;
const int N = 2e3+9;
int a[N],n,m,xx,yy,tot,e;
int vis[N],flag[N],ans;
int temp[N][N],kk;
struct Node
{
int it,son[N],ru,ru2;
}edge[N];
struct node
{
int son[N],num;
}T[N];
void check(){for(int i=1;i<=tot;i++){cout<<"!"<<edge[i].it<<" "<<edge[i].ru<<endl;for(int j=1;j<=edge[i].ru2;j++)cout<<edge[i].son[j]<<" ";cout<<"_____________"<<endl;}}
void check2(){for(int i=1;i<=n;i++){if(!T[i].num)continue;cout<<">>>>>"<<endl<<i<<" "<<T[i].num<<endl;for(int j=1;j<=T[i].num;j++){cout<<T[i].son[j]<<" ";}cout<<endl<<"<<<<"<<endl;}}
int main()
{
cin>>n>>m>>e;
for(int i=1;i<=e;i++)
{
scanf("%d%d",&xx,&yy);yy+=n;
if(temp[xx][yy])continue;temp[xx][yy]=temp[yy][xx]=1;
if(!vis[yy])vis[yy]=++tot;
T[xx].num++;T[xx].son[T[xx].num]=yy;edge[vis[yy]].ru++;edge[vis[yy]].ru2++;edge[vis[yy]].it=yy;edge[vis[yy]].son[edge[vis[yy]].ru]=xx;
}
while(kk!=tot)
{
int zz=N,i;
for(int j=1;j<=tot;j++)if(!flag[edge[j].it]&&edge[j].ru<zz)zz=edge[j].ru,i=j;
int mi=N,mark;
for(int j=1;j<=edge[i].ru2;j++){int v=edge[i].son[j];if(flag[v])continue;if(T[v].num<mi)mi=T[v].num,mark=v;}flag[edge[i].it]=1,flag[mark]=1,ans++,kk++;
for(int j=1;j<=T[mark].num;j++){edge[vis[T[mark].son[j]]].ru--;if(!edge[vis[T[mark].son[j]]].ru){if(edge[i].it!=T[mark].son[j]&&!flag[T[mark].son[j]])kk++;flag[T[mark].son[j]]=1;}}
}
cout<<ans<<endl;
return 0;
}
大体思路就是找到所有右部端点中入度最小的点的所有相连的点(左边)中出度最小的点,再用这个点(左边)把它相连的点(右边)的出度更新