学习心得 - 算法 - 匈牙利(增广路算法)
整个二分图,就是一个不断修改的 Romatic 史。
情人节特辑?或许是吧。
什么是二分图最大匹配
左边
我们要让左右 ♥ 两 ♥ 两 ♥ 匹 ♥ 配 ♥,求最大 ♥ 匹 ♥ 配 ♥ 对 ♥ 数。
算 ♥ 法 ♥ 演 ♥ 示
在这里我们使用匈牙利算法。
首先我们需要一些人。
左边是 ♥ 男 ♥ 孩 ♥ 纸。
右边是 ♥ 女 ♥ 孩 ♥ 纸。
我们把此题的样例
注意到我们可以成全最多
还有其他很多匹配方法,但是答案为
我们想如何匹配?
我们考虑枚举左侧节点,再通过搜索搜出他的 npy 匹配节点。
我们通过图片来理解一下。
男 1 号
我们枚举 NPY 时可以枚举到女
女 1 号
她还没有 NPY,所以我们将女
女 2 号
男
记录答案
男
男 2 号
孤独的男
男 3 号
男
女 1 号
已经被男
我们先让男
接着,让男
太好了,我们的匹配情况就变成了:
女 2 号
已经被男
记录答案
男
男 4 号
啥也不是。。。
女 2 号
男
无语。最终没有 NPY T^T
最终状态
匹配对数
匈牙利算法
我们刚刚做的匹配操作,就是匈牙利算法。
家长:建议让 OI 不要再伤害青少年之匈牙利算法。
考虑使用
- 首先枚举占有女
v 号。 - 然后判断是否能成功 ♥ 与 ♥ 女 ♥
v ♥ 号 ♥ 配 ♥ 对 ♥。细说配对。- 要是
npy_v=0 ,那好皆大欢喜。 - 否则是遇上情敌了,以出题人给的强悍力量让原有
npy_v 考虑换 NPY,要是换不了那么占有失败,否则匹配成功。
- 要是
- 统计一下有多少次匹配成功即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
int n,m,ee,U,V,npy[N],ncnt;
int found[N];
bool e[N][N];
bool dfs(int p){
for(int v=1;v<=m;v++)if(e[p][v]&&!npy[v]){
npy[v]=1;
if(!found[v]||dfs(found[v])){
found[v]=p;
return 1;
}
}
return 0;
}
int main(){
cin>>n>>m>>ee;
for(int i=1;i<=ee;i++){
cin>>U>>V;
e[U][V]=1;
}
for(int i=1;i<=n;i++){
memset(npy,0,sizeof(npy));
if(dfs(i))++ncnt;
}
cout<<ncnt;
return 0;
}
最后,祝愿广大 OIer 早日找到 NPY
(虽然这不可能——From Anguei