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;
}