您的位置:首页 > 其它

匈牙利算法 求二分图最大匹配

2017-11-22 13:49 337 查看

一直没有学习匈牙利算法,因为网络流实现匹配的功能已经足够强大了。

但今天这道题【BZOJ1191】用网络流实在难以解决动态匹配,而鉴于匈牙利算法实现的代码复杂度极小,所以今天学习一下。


匈牙利算法用于解决二分图匹配问题,主要思想是增广路,对于当前左点u,若能找到一个相连的未匹配的右点v,则直接匹配,否则进行尝试更改其他已匹配的右点匹配的左点的匹配对象【递归】,若成功则匹配成功


二分图匹配问题还有很多变式:

最小点覆盖集 = 最大点独立集 = 最大匹配

最小路径覆盖数 = 点数 - 最大匹配


上题:

BZOJ1191

大意:二分图匹配= =

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 1005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1;char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
return out * flag;
}
int n,m,lk[maxn],vis[maxn];
int head[maxn],nedge = 0;
struct EDGE{int to,next;}edge[maxm];
inline void build(int u,int v){
edge[nedge] = (EDGE){v,head[u]};
head[u] = nedge++;
}
bool find(int u){
int to;
Redge(u) if (!vis[to = edge[k].to]){
vis[to] = true;
if (!lk[to] || find(lk[to])){
lk[to] = u;
return true;
}
}
return false;
}
int main()
{
fill(head,head + maxn,-1);
int ans = 0;
n = read(); m = read();
REP(i,m) build(i,read()),build(i,read());
REP(i,m){
memset(vis,0,sizeof(vis));
if (find(i)) ans++;
else break;
}
cout<<ans<<endl;
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: