二分图匹配 匈牙利算法
先让我来介绍一下二分图是什么吧!
这就是一种最常见的二分图。也就是左右两边相连,左边与左边不连,右边也不连的一幅图。把左边看成集合A,右边看成集合B,每条边都连接A与B中的点。
讲完二分图,我们在了解一下匹配是什么。
在二分图中,任意两条边都没有公共顶点。
让我们看一幅图:
红色线条就是匹配的线条,当然,不止一种。
这些红色线条可以称为匹配边,被红色线条连接的点可以称为匹配点。
最大匹配:在一个匹配图中,匹配边最多的叫做最大匹配,上图的最大匹配是3条边。
完美匹配:所以顶点都是匹配点的图就是完美匹配,当然,也是最大匹配。
介绍完二分图匹配,我们就先看一道洛谷的试题:
P3386 【模板】二分图匹配
题目背景
二分图
题目描述
给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数
输入格式:
第一行,n,m,e
第二至e+1行,每行两个正整数u,v,表示u,v有一条连边
输出格式:
共一行,二分图最大匹配
输入样例#1:
1 1 1
1 1
输出样例#1:
1
说明
n,m≤1000,1≤u≤n,1≤v≤mn,m≤1000,1≤u≤n,1≤v≤m
因为数据有坑,可能会遇到 v>mv>m 的情况。请把 v>mv>m 的数据自觉过滤掉。
算法:
二分图匹配
像这类题目,我们通常用匈牙利来解决。
假设二分图是这样的(你可以理解为相亲,连接的表示相互有好感):
我们按左边的顺序来。
第一次1选择4(用红线描出)
第二次2选择,但是突然发现4被连了,所以果断抢过4,让1再选一个。
这时的一还有新的选择,于是1连到了5。
图就变成了这样:
第三次3选择,但是5和4都被抢了。所以先抢过4,2一看4被抢了,又找不到其他的了,于是就跑回来抢回4。3只能抢5,但1一看5和4都被抢了,就跑回来抢回5。然后3就只能在一旁画圈圈了QAQ。
6:”怎么没人选我QAQ。”
所以这幅图的最大匹配就是2。
是不是很好理解啊~
下面贴上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,e,gl[1005],ans;
bool vis[1005][1005],usd[1005];
bool fnd(int x){
for(int i=1;i<=m;i++)
if(vis[x][i]&&!usd[i]){
usd[i]=1;
if(gl[i]==0||fnd(gl[i])){gl[i]=x;return 1;}//如果i没有匹配,或者调整后可以匹配,就将这个匹配。
}
return 0;
}
int main(){
freopen("prob.in","r",stdin);
freopen("prob.out","w",stdout);
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=e;i++){
int x,y;scanf("%d%d",&x,&y);
vis[x][y]=1;
}
for(int i=1;i<=n;i++) memset(usd,0,sizeof(usd)),ans+=fnd(i);//如果匹配就+1
printf("%d\n",ans);
return 0;
}
如果有错请留言,谢谢大家o( ^ v ^ )o