基本概念
- 匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点。
- 最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
- 完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。
- 交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。
- 增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替 路称为增广路(agumenting path)。
简单来说就是一个舞会中,男女最多一对一可以配多少对舞伴
匈牙利算法
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 1e5 + 100;
vector<int> edge[N];
inline void add(int x, int y){
edge[x].push_back(y);
}
//match[j]=a,表示女孩j的现有配对男友是a
int match[N];
//st[]数组我称为临时预定数组,st[j]=a表示一轮模拟匹配中,女孩j被男孩a预定了。
int st[N];
//这个函数的作用是用来判断,如果加入x来参与模拟配对,会不会使匹配数增多
int find(int from) {
//遍历自己喜欢的女孩
for (auto & to : edge[from]) {
if (!st[to])//如果在这一轮模拟匹配中,这个女孩尚未被预定
{
st[to] = true;//那x就预定这个女孩了
//如果女孩j没有男朋友,或者她原来的男朋友能够预定其它喜欢的女孩。配对成功,更新match
if (!match[to] || find(match[to])) {
match[to] = from;
return true;
}
}
}
//自己中意的全部都被预定了。配对失败。
return false;
}
int n1, n2, m;
int main(){
cin >> n1 >> n2 >> m;
for(int i = 0; i < m; ++i){
int x, y;
cin >> x >> y;
add(x, y);
}
int res = 0;
for (int i = 1; i <= n1; i++) {
memset(st, false, sizeof st);
if (find(i)) {
res++;
}
}
cout << res << endl;
return 0;
}