【模板】二分图最大匹配
题目描述
给定一个二分图,其左部点的个数为 n n n,右部点的个数为 m m m,边数为 e e e,求其最大匹配的边数。
左部点从 1 1 1 至 n n n 编号,右部点从 1 1 1 至 m m m 编号。
输入格式
输入的第一行是三个整数,分别代表 n n n, m m m 和 e e e。
接下来 e e e 行,每行两个整数 u , v u, v u,v,表示存在一条连接左部点 u u u 和右部点 v v v 的边。
输出格式
输出一行一个整数,代表二分图最大匹配的边数。
样例 #1
样例输入 #1
1 1 1
1 1
样例输出 #1
1
样例 #2
样例输入 #2
4 2 7
3 1
1 2
3 2
1 1
4 2
4 1
1 1
样例输出 #2
2
提示
数据规模与约定
对于全部的测试点,保证:
- 1 ≤ n , m ≤ 500 1 \leq n, m \leq 500 1≤n,m≤500。
- 1 ≤ e ≤ 5 × 1 0 4 1 \leq e \leq 5 \times 10^4 1≤e≤5×104。
- 1 ≤ u ≤ n 1 \leq u \leq n 1≤u≤n, 1 ≤ v ≤ m 1 \leq v \leq m 1≤v≤m。
不保证给出的图没有重边。
代码
//夸张哪个
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510,M = 5e4+10;
int n,m,k;
int e[M],ne[M],h[N],idx;
int match[N];
int ans;
bool st[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool find(int x){
for(int i=h[x];~i;i=ne[i]){
int j=e[i];
if(st[j])continue;
st[j]=true;
if(!match[j]||find(match[j])){
match[j]=x;
return true;
}
}
return false;
}
int main(){
cin>>n>>m>>k;
memset(h,-1,sizeof h);
while(k--){
int a,b;
cin>>a>>b;
add(a,b);
}
for(int i=1;i<=n;i++){
memset(st,0,sizeof st);
if(find(i)){
ans++;
}
}
cout<<ans;
return 0;
}