二分图匹配 【匈牙利算法】 从入门到熟练

二分图匹配 匈牙利算法


先让我来介绍一下二分图是什么吧!

这里写图片描述

这就是一种最常见的二分图。也就是左右两边相连,左边与左边不连,右边也不连的一幅图。把左边看成集合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,m10001un1vm
因为数据有坑,可能会遇到 v>m 的情况。请把 v>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

posted @ 2018-02-26 19:25  XSamsara  阅读(175)  评论(0编辑  收藏  举报