http://poj.org/problem?id=3041
二分图匹配的详解:https://www.renfei.org/blog/bipartite-matching.html
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
//以下说的左顶点集是指増广路的未匹配点起点所在的顶点集合
//----------------------------------------------------
//result_x[i]=j;表示左顶点集的点i连接到右顶点集的点j,同理。。
int result_x[505],result_y[505];
int vis[505];//vis[i]标记点i有没有被走过
vector<int > p[505];//相当于线性表
bool dfs(int u){//左顶点集合的未匹配点
ll len=p[u].size();
for(int i=0;i<len;i++){//寻找顶点u在右顶点集和的邻接点
int v=p[u][i];
if(!vis[v]) {//如果此邻接点在此次dfs找増广路的过程中没有被走过
vis[v]=1;//加入到増广路
if(!result_y[v]||dfs(result_y[v])){//!result_y[v]如果此邻接点未匹配过(不属于前一个匹配M)
//dfs(result_y[v])如果此邻接点匹配过,继续判断以此点为未匹配起点的新的増广路是否存在
result_y[v]=u;//找到增广路,就可以交换増广路中的匹配边和未匹配边
result_x[u]=v;
return true;
}
}
}
return false;
}
int getnum(int n){
memset(result_x,0,sizeof(result_x));
memset(result_y,0,sizeof(result_y));
int ans=0;
for(int u=1;u<=n;u++){
if(!result_x[u]){//如果是未匹配点可以找増广路
memset(vis,0,sizeof(vis));
if(dfs(u)){
ans++;
}
}
}
return ans;
}
int main(){
ll n,k,x,y;
cin>>n>>k;
for(int i=0;i<k;i++){
cin>>x>>y;
p[x].push_back(y);
}
cout<<getnum(n)<<endl;
return 0;
}