二分图:
将左列当作男生,右边当作女生,一个男生只能与一个女生配对;
匈牙利(ntr)算法:
对所有男生进行遍历,为他寻找对象;
如果与这个男生有暧昧关系的女生已经与其他的男生配对:
就进行查找,是否能利用其她女生,使自己成功ntr之前与该女生配对的男生:
ntr成功:该女生成功成为你的对象;
ntr失败:继续往后查找是否能与别的有暧昧关系的女生配对;
否则:就将该女生成为你的对象;
代码:
首先使用链式前向星存图:
int match[N] , e[M] , ne[M] , h[N] , idx;
void add(int a,int b){
e[idx] = b , ne[idx] = h[a] , h[a] = idx ++;
}
查找函数:
st代表当前这个女生是否被查询;
match表示这个女生的对象是谁;
bool find(int t){
for(int i = h[t] ; ~i ; i = ne[i]){
int x = e[i];
if(!st[x]){
st[x] = 1;
if(!match[x] || find(match[x])){
match[x] = t;
return true;
}
}
}return false;
}
总代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 505 , M = 100005;
int match[N] , e[M] , ne[M] , h[N] , idx;
int n1 , n2 , m;
bool st[N];
void add(int a,int b){
e[idx] = b , ne[idx] = h[a] , h[a] = idx ++;
}
bool find(int t){
for(int i = h[t] ; ~i ; i = ne[i]){
int x = e[i];
if(!st[x]){
st[x] = 1;
if(!match[x] || find(match[x])){
match[x] = t;
return true;
}
}
}return false;
}
int main(){
cin >> n1 >> n2 >> m;
memset(h, -1 , sizeof h);
idx = 0;
while(m --){
int a , b;
cin >> a >> b;
add(a,b);
}
int ans = 0;
for(int i = 1 ; i <= n1 ; i ++){
memset(st , 0 , sizeof st);
if(find(i))ans ++;
}
cout << ans << endl;
}