AcWing 861. 二分图的最大匹配-个人理解与剧情注释
原题链接
简单
作者:
现代修士o_O
,
2021-04-30 22:29:15
,
所有人可见
,
阅读 263
//勇敢找女朋友的算法,人生道理:错过比失败更加难受
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 510, M = 100010;
int n1, n2, m;//二分图左半部点数n1,右半部点数n2,边数m
int h[N], e[M], ne[M], idx;//邻接表存心仪的女生(可能匹配成功的点),注意e[],ne[]数组大小与边数相关
int match[N];//女生目前牵手(匹配成功)的男生,0代表没还没牵手(匹配成功)
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 != -1; i = ne[i])//遍历x男生每个心仪的女生
{
int j = e[i];//女生编号j
if (!st[j])//没有尝试过与j女生表白过,勇敢进行表白!
{
st[j] = true;//先标记这是我x男生要表白的j女生,对j女生可能存在的现男友发起冲击
if (!match[j] || find(match[j]))//j女生还没对象,或她现男友原来还有备胎(有意思),把j女生让给我x男生!霸气!😀
{
match[j] = x;//j女生与x男生牵手成功!
return true;//单纯告诉月老这个好消息或告诉这个消息给上一层的兄弟(此时他找备胎😓成功)
}
}
}
return false;//心仪女生都拒绝了他。x兄弟,天涯何处无芳草,何必单恋几支花呢?不会背叛的纸片人,她不香吗?😄
}
int main()
{
cin >> n1 >> n2 >> m;
memset(h, -1, sizeof h);//这一步太容易忘记了,记得邻接表一定要在add之前初始化
for (int i = 0; i < m; i ++ )
{
int a, b;
scanf("%d%d", &a, &b);//初始化每个男生心仪的女生。如果没有的话,emm
add(a, b);
}
int res = 0;//成功匹配的个数,初始化0
for (int i = 1; i <= n1; i ++ )//遍历每个男生。男生的编号从1开始,总数n1
{
memset(st, 0, sizeof st);//不要被上一个男生的行为干扰了,勇往直前!
if (find(i)) res ++ ;
}
cout << res << endl;
return 0;
}