[图论] 二分图匹配(匈牙利算法)

介绍部分转载于维基百科:

匈牙利算法是众多用于解决线性任务分配问题的算法之一,是用来解决二分图最大匹配问题的经典算法,可以在多项式时间内解决问题,由美国数学家Harold Kuhn 于1955年提出。此算法之所以被称作匈牙利算法是因为算法很大一部分是基于以前匈牙利数学家Dénes K?nig和Jen? Egerváry的工作之上创建起来的.

问题简介:

设G=(V,E)是一个无向图。如顶点集V可分区为两个互不相交的子集V1,V2之并,并且图中每条边依附的两个顶点都分属于这两个不同的子集。则称图G为二分图。二分图也可记为G=(V1,V2,E)。

给定一个二分图G,在G的一个子图M中,M的边集{E}中的任意两条边都不依附于同一个顶点,则称M是一个匹配。 选择这样的子集中边数最大的子集称为图的最大匹配问题(maximal matching problem)

如果图的所有顶点都与某匹配中的一条边相关联,则称此匹配为完全匹配,也称作完备,完美匹配。

算法描述:

  求最大匹配的一种显而易见的算法是:先找出全部匹配,然后保留匹配数最多的。但是这个算法的时间复杂度为边数的指数级函数。因此,需要寻求一种更加高效的算法。下面介绍用增广路求最大匹配的方法(称作匈牙利算法,由数学家Harold Kuhn于1955年提出)。

  增广路的定义(也称增广轨或交错轨):

  若P是图G中一条连通两个未匹配顶点的路径,并且属于M的边和不属于M的边(即已匹配和待匹配的边)在P上交替出现,则称P为相对于M的一条增广路径。(M为一个匹配)

  由增广路的定义可以推出下述三个结论:

  1-P的路径长度必定为奇数,第一条边和最后一条边都不属于M。

  2-将M和P进行异或操作(去同存异)可以得到一个更大的匹配M’。

  3-M为G的最大匹配当且仅当不存在M的增广路径。

  算法轮廓:

  (1)置M为空

  (2)找出一条增广路径P,通过异或操作获得更大的匹配M’代替M

  (3)重复(2)操作直到找不出增广路径为止

时间空间复杂度:

  时间复杂度 邻接矩阵:最坏为O(n^3) 邻接表:O(mn)   空间复杂度 邻接矩阵:O(n^2) 邻接表:O(m+n)

比较直观得了解匹配过程可以参考博客:http://blog.csdn.net/dark_scope/article/details/8880547

个人备忘录:二分图中,左边的顶点个数假设为un,右边的顶点个数假设为vn,g[i][j]表示左边定点i和右边顶点j之间有边相连,用linked[i]表示与右边第i个顶点相匹配的是左边哪个顶点。首先遍历左边定点,为每个左边顶点去匹配右边的顶点,如果发现一个可行匹配,就标记为右边顶点已被匹配,该左边定点的匹配过程到此结束,然后去遍历下一个左边顶点,如果与该左边顶点有边的右边顶点已经被匹配了,假设与它匹配的左边顶点是X,那么就要重新为X去匹配,看能不能把该右边顶点让给当前需要匹配的左边定点。。有点绕。。举个例子
比如左边顶点a 和右边 c,d有边,左边顶点b和右边顶点c有边,一开始匹配的是a,a和c匹配,a的匹配结束,然后去匹配b,发现和b有边相连的右边顶点c已经被匹配了,而与之匹配的顶点是左边顶点a,那么就重新对a进行匹配,看能不能a去匹配另一个顶点,而把c这个顶点“腾出空位来”,发现,a也可以和d匹配,可以腾出一个空来使b和c相匹配。这就是匈牙利算法比较关键的地方。

模板:hdu 2063

/*
匈牙利算法解决二分图最大匹配问题
采用的邻接矩阵的形式,g[i][j]
maxn代表一边最多的顶点数,un代表左边顶点数,vn代表右边顶点数
linked[i]代表右边的第i个点与左边哪个点相匹配
*/

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=502;
int un,vn;//左边顶点数,右边顶点数
int g[maxn][maxn];//邻接矩阵来存储边
int linked[maxn];//右边的点和左边的哪个点匹配
bool vis[maxn];

bool dfs(int u)
{
    for(int v=1;v<=vn;v++)//遍历右边顶点
    {
        if(g[u][v]&&!vis[v])
        {
            vis[v]=1;
            if(!linked[v]||dfs(linked[v]))//右边顶点还没有被匹配,或者已经匹配的前面左边顶点可以去寻找另一个匹配而把该右边顶点“腾出空位”让给当前左边顶点u
            {
                linked[v]=u;
                return true;
            }
        }
    }
    return false;
}

int hungary()
{
    int ans=0;
    memset(linked,0,sizeof(linked));
    for(int u=1;u<=un;u++)//遍历左边顶点,去寻找与之匹配的右边顶点
    {
        memset(vis,0,sizeof(vis));
        if(dfs(u))//去找u能不能匹配,如果可以匹配的话,ans++
            ans++;
    }
    return ans;
}

int k,m,n;//m为题目中要求输入的左边顶点数,n为题目中要求输入的右边顶点数
int main()
{
    while(scanf("%d",&k)!=EOF&&k)
    {
        scanf("%d%d",&m,&n);
        un=m;vn=n;
        memset(g,0,sizeof(g));
        int u,v;
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d",&u,&v);//u和v有边
            g[u][v]=1;
        }
        printf("%d\n",hungary());
    }
    return 0;
}
时间: 2024-08-20 23:10:54

[图论] 二分图匹配(匈牙利算法)的相关文章

图论-二分图匹配-匈牙利算法

有关概念: 二分图:图G中的点集可以分为两个互不相交的子集,且G中的每条边连接的两个点分别属于这两个子集 二分图匹配:二分图G的子图M中每个结点上只连一条边,则称M为一个匹配 极大匹配:无法再向二分图中加边且满足匹配条件的匹配 最大匹配:所有极大匹配中边数最多的一个 增广路:若P为图G上连接两个未匹配结点的路径,且已匹配边和未匹配边在P上交替出现,则称P为相对于M的一条增广路 匈牙利算法即用来求二分图的极大匹配 思路: 在图G中找出增广路P,对P上每一条边取反(即已匹配边改为未匹配边,未匹配边改

USACO 4.2 The Perfect Stall(二分图匹配匈牙利算法)

The Perfect StallHal Burch Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John r

HDU 5943 Kingdom of Obsession 【二分图匹配 匈牙利算法】 (2016年中国大学生程序设计竞赛(杭州))

Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 49    Accepted Submission(s): 14 Problem Description There is a kindom of obsession, so people in this kingdom do things very

HDU1507 Uncle Tom&#39;s Inherited Land* 二分图匹配 匈牙利算法 黑白染色

原文链接http://www.cnblogs.com/zhouzhendong/p/8254062.html 题目传送门 - HDU1507 题意概括 有一个n*m的棋盘,有些点是废的. 现在让你用1*2的矩形覆盖所有的不废的点,并且不重叠,问最多可以覆盖多少个1*2的矩形,输出方案,有SPJ. 输入描述: 多组数据,每组首先两个数n,m(如果n和m为0,则结束程序) 然后给出k 然后给出k个二元组(x,y)表示废点的坐标. 题解 按照前两片博文的算法已经不行了,因为方案不对了. 所以我们要进行

矩阵游戏|ZJOI2007|BZOJ1059|codevs1433|luoguP1129|二分图匹配|匈牙利算法|Elena

1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MB Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏--矩阵游戏.矩阵游戏在一个N *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择 矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换 对应格子的颜色)游戏的目标,即通过若干次操作,

网络流24题 第一题 - 洛谷2756 飞行员配对方案 二分图匹配 匈牙利算法

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 题意概括 裸的二分图匹配 题解 匈牙利算法 上板子 代码 #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=100+5; int m,n,a,b,match[N

BZOJ 1191 [HNOI2006]超级英雄Hero:二分图匹配 匈牙利算法

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1191 题意: 有m道题,每答对一题才能接着回答下一个问题. 你一道题都不会,但是你有n个"锦囊妙计"(每个只能用一次). 对于每道题,你只能用该题规定的两种锦囊中的一种,来解决这道题. 问你最多能解决多少道题. 题解: 二分图最大匹配. 匈牙利算法. 问题与锦囊匹配. 最大匹配即为最多回答数. 但是题目中要求题目必须连续回答,不能中断. 所以在给每一个问题配对时,一旦匹配不上,

#图# #二分图匹配# #匈牙利算法#

二分图 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图. 区别二分图,关键是看点集是否能分成两个独立的点集. 二分图匹配(匈牙利算法) 最大匹配:设 是一个无向图.如顶点集V可分割为两个互不相交的子集 ,选择这样的子集中边数最大的子集称为图的最大匹配问题(maximal matching problem). 完全匹配:如果一个匹配中,  且

二分图匹配 匈牙利算法 hihocoder 1122

#1122 : 二分图二?二分图最大匹配之匈牙利算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了.因为过年时间并不是很长,所以姑姑希望能够尽可能在一天安排比较多的相亲.由于一个人同一天只能和一个人相亲,所以要从当前的相亲情况表里选择尽可能多的组合,且每个人不会出现两次.不知道有没有什么好办法,对于当前给定的相亲情况表,能够算出最多能同时安排多少组相亲呢? 同样的,我们先将给定的情况表转

【转】二分图匹配 匈牙利算法介绍

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. -------等等,看得头大?那么请看下面的版本: 通过数代人的努力,你终于赶上了剩男剩女的大潮,假设你是一位光荣的新世纪媒人,在你的手上有N个剩男,M个剩女,每个人都可能对多名异性有好感(-_-||暂时不考虑特殊的性取向),如果一对男女互有好感,那么你就可以把这一对撮合在一起,现在