二分图匹配相关算法讲解
张天翔
blog.csdn.net/hzoi_ztx
[email protected]
二分图 (BipartiteGraph) 又称作二部图,是图论中的一种特殊模型。
设 G=(V,E) 是一个无向图,如果顶点 V 可分割为两个互不相交的子集 (X,Y) ,并且图中的每条边 (i,j) 所关联的两个顶点 i 和 j 分别属于这两个不同的顶点集 (i∈X,j∈Y) ,则称图 G 为一个二分图。
简而言之,就是顶点集 V 可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。
如果 G 中 X 的每个顶点都与 Y 的每个顶点相邻,则称 G 为完全二分图。
注意,二分图是无向图,但是有些问题虽然是有向图的外壳,实际上还是二分图的解决方法,后面会有一些例子。
/ 你 / 可 / 以 / 将 / X / 中 / 的 / 点 / 看 / 做 / 女 / 生 / , / Y / 中 / 的 / 点 / 看 / 作 / 男 / 生 / , / 然 / 后 / 在 / 不 / 发 / 生 / 同 / 性 / 恋 / 的 / 情 / 况 / 下 / X / X / X / 来 / 理 / 解 / 一 / 下 / 二 / 分 / 图 / 。
匹配是在图中定义的,二分图中的匹配也是下面这些定义,你可以动手画一画。
设 G=(V,E) 是一个图, M 是 E 的一个子集,如果 M 不含环且任意两边都不相邻,则称 M 为 G 的一个匹配。
G 中边数最多的匹配称为 G 的最大匹配。
下面设 M 是 G 的一个匹配。
对于图 G=(V,E) ,在每条边 ei 上赋一个实数权 wi 。定义 ∑ei∈Miwi 为匹配 M 的权。 G 中权最大的匹配称为 G 的最大权匹配。其中,若 ∀ei∈E , wi=c,(c 为非负常数 ) ,则 G 的最大权匹配就是 G 的最大匹配。上面的例图显然最大匹配数是 4 。
若 ∀vi∈V , vi 与 M 中的边相关联,则称 vi 是 M 饱和点,否则称 vi 为 M 非饱和点。
如果 G 中每个顶点都是 M 饱和点,则称 M 为 G 的完美(备)匹配。
显然, X 与 Y 点集大小需要相等。
举个栗子,我有 5 只母鸡, 4 只公鸡,可以看上面那张图。
每只母鸡和公鸡都有自己的好朋友(用边表示),它们可以生下一只小鸡,不是好朋友的则不可以产生后代。我决定让它们实行一夫一妻制。问,如何安排它们才能得到最多的小鸡?拒绝二胎和乱伦 这就是最大匹配的一个问题。。。
设 P 是 G 的一条链。如果 P 的边交替地一条是 M 中的边,一条不是 M 中的边,则称 P 为 M 交错轨。类似地,我们可以定义 G 的交错圈。易知, G 的交错圈一定是偶圈。
一条连接两个不同的 M 非饱和点的 M 交错链称为 M 增广轨。
增广轨定理:
覆盖同样是在图中定义的,但因为二分图中有其特殊性,直接给出二分图中覆盖的相关概念。
覆盖分为点覆盖和边覆盖,分别是用一个点集关联所有边(使所有的边至少有一个端点属于此点集)和用一个边集关联所有点(使所有的点为此边集中至少一条边的端点)。
最小覆盖(最小点覆盖)点最少的点覆盖
König定理:
在最大匹配 M 中,我们取每一条匹配边上的一个端点(当然不是随便取的,后面会介绍算法求此点集),个数为 m .
(1) m 个点是足够的。只需要让它们覆盖最大匹配的 m 条边,则其它边一定被覆盖(如果有边 e 不被覆盖,把 e 加入后得到一个更大的匹配)
(2) m 个点是必需的。仅考虑形成最大匹配的这 m 条边,由于它们两两无公共点,因此至少需要 m 个点才能把它们覆盖。
证毕。
举个栗子,任务安排(黑书P331) 问题。
最小边覆盖边最少的边覆盖
独立集即一个点集,集合中任两个结点不相邻,则称 V 为独立集。或者说是导出的子图是零图(没有边)的点集。
最大独立集点最多的独立集。
独立数:最大独立集的点。
很显然的把最大匹配两端的点都从顶点集中去掉这个时候剩余的点是独立集,这是 |G|−2⋅|M| ,同时必然可以从每条匹配边的两端取一个点加入独立集并且保持其独立集性质,故为 |G|−|M| 。
举个栗子,棋盘上的骑士问题(黑书P332)。棋盘上放置最多的骑士(马)不互相攻击。
边独立集即一个边集,满足边集中的任两边不邻接。
最大边独立集:边最多的边独立集。
边独立数*:最大边独立集的边数。
可以看到:边独立集就是匹配,最大匹配即最大边独立集。一般情况下称匹配。
一个无向图 G=(V,E) 。取 V 的一个子集 U ,若对于 U 中任意两个点 u 和 v ,有边 (u,v)∈E ,那么称 U 是 G 的一个完全子图。 U 是一个团当且仅当 U 不被包含在一个更大的完全子图中。
G 的最大团指的是定点数最多的一个团。
最小路径覆盖:是“路径” 覆盖“点”,即用尽量少的不相交简单路径覆盖* 有向无环图 G *的所有顶点,即每个顶点严格属于一条路径。路径的长度可能为 0 (单个点)。
可以直观地想象一下,在一个有向无环图中至少放几个人才能走到所有点?最少的人数就是最小路径覆盖数。
容易想到
有向无环图(DAG)的最小路径覆盖,可以用二分图最大匹配来求解。
(1)如果匹配数为零,那么 G 中不存在有向边,于是显然有:
最小路径覆盖=|G|-最大匹配数=|G|-0=|G|
即 G 的最小路径覆盖数为 G
(2) G′ 中暂时不存在匹配边时,路径覆盖数为 |G| 。此时如果在 G′ 中增加一条匹配边 xi→yj ,那么在图P的路径覆盖中就存在边 i→j ,也就是说边 i→j 在某一条路径上,于是路径覆盖数就可以减少一个。如此继续增加匹配边,每增加一条,路径覆盖数就减少一条;直到匹配边不能继续增加时,路径覆盖数也不能再减少了,此时就有了前面的公式。
但是这只是说明了每条匹配边对应于路径覆盖中的一条路径上的某一条有向边,下面来说明一个路径覆盖中的每条有向边对应于一条匹配边。与前面类似,对于路径覆盖中的每条连接两个顶点之间的每条有向边 i→j ,我们可以在匹配图中对应做一条边 xi→yj , 显然这样做出来图的是一个匹配图(这一点用反证法很容易证明,如果得到的图不是一个匹配图,那么这个图中必定存在这样两条边 xi→yj 及 xi→yk , (j≠k) ,那么在路径覆盖图中就存在了两条边 i→j , i→k ,那从 i 出发的路径就不止一条了,这与路径覆盖图是矛盾的;还有另外一种情况就是存在 xi→yj , xk→yj ,这种情况也类似可证)
至此,就说明了匹配边与路径覆盖图中连接两顶点之间边的一一对应关系,那么也就说明了前面的公式成立!
铲雪车问题。
稍稍总结一下二分图的性质
要求解二分图问题,首先需要判定其为二分图。
1.
二分图:有两顶点集且图中每条边的的两个顶点分别位于两个顶点集中,每个顶点集中没有边直接相连接
2.
无向图G为二分图的充分必要条件是:G至少有两个顶点,且其所有回路的长度均为偶数。
3.
判断二分图的常见方法是染色法:开始对任意一未染色的顶点染色,之后判断其相邻的顶点中,若未染色则将其染上和相邻顶点不同的颜色,若已经染色且颜色和相邻顶点的颜色相同则说明不是二分图,若颜色不同则继续判断,bfs和dfs可以搞定!(易知:任何无回路的图均是二分图。)
问题
给定一个二分图 G ,求 G 的最大匹配数
匈牙利算法
算法思想:
根据一个匹配是最大匹配当且仅当没有增广路,求最大匹配就是找增广轨,直到找不到增广轨,就找到了最大匹配。遍历每个点,查找增广路,若找到增广路,则修改匹配集和匹配数,否则,终止算法,返回最大匹配数。
增广路径必须满足的性质
- 有奇数条边。
- 起点在二分图的左半边,终点在右半边。
- 路径上的点一定是一个在左半边,一个在右半边,交替出现。(其实二分图的性质就决定了这一点,因为二分图同一边的点之间没有边相连,不要忘记哦。)
- 整条路径上没有重复的点。
- 起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。
- 路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。
- 最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个(奇数=偶数+1)。而每次查找得到的增广路径的长度都是在上一次查找到的增广路径的基础上延伸的,这样每次更新匹配数都是增加1。
匈牙利算法步骤
令 G=(X,∗,Y) 是一个二分图,其中, X={x1,x2,...xm},Y={y1,y2,...yn} 。令 M 为 G 中的任一个匹配
1. 置 M 为空
2. 从 G 中找出一个未匹配点 v (增广路性质5要求的),如果没有则算法结束,否则,以 v 为起点,查找增广路(邻接点是为未匹配点,则返回寻找完成,若 v 的邻接点 u 是匹配点,则从 u 开始查找,直至查找到有未匹配点终止)即满足增广路的性质,如果没有找到增广路,则算法终止
3. 找出一条增广路径 P ,通过异或(取反)操作获得更大的匹配 M′ 代替 M (方便要输出增广矩阵以及进一步查找),匹配数加1(性质7得到)
4. 重复(2)(3)操作直到找不出增广路径为止彻底理解增广路
- 总是从X集的未匹配点出发,寻找匹配点或者未匹配点,如查找到未匹配点则该增广路终止,否则以该点的增广路不存在。
- 每次查找增广路都是在之前形成的匹配(上面步骤3中异或后的匹配)的基础上进行延伸的,也就是查找匹配点总是在匹配M中,其实就是用起点和终点两个未匹配点将得到匹配的边尽可能的连接起来的增广路,这样增广路长度就延长了,当然也可以是直接就是以两个个未匹配点的边(就直接添加进匹配中)。总而言之,每次扩充匹配不是通过延伸增广路径就是新增增广路径(当然长度为1)。
时间空间复杂度
时间复杂度
邻接矩阵:最坏为 O(n3) 邻接表: O(mn)
空间复杂度
邻接矩阵: O(n2) 邻接表: O(m+n)匈牙利算法实现
匈牙利算法只需要以每个节点为起点找一次增广路即可求得最大匹配,寻找增广路的复杂度为 O(E) ,总的复杂度为 O(VE) 。
下面的实现是查找从X到Y的匹配,X中每一个点最多只能被遍历一次用于查找增广路(当已经是匹配点是就不遍历了)
// 由于时间紧凑,代码摘自http://dsqiu.iteye.com/blog/1689505
#define maxn 10//表示x集合和y集合中顶点的最大个数!
int nx,ny;//x集合和y集合中顶点的个数
int edge[maxn][maxn];//edge[i][j]为1表示ij可以匹配
int cx[maxn],cy[maxn];//用来记录x集合中匹配的y元素是哪个!
int visited[maxn];//用来记录该顶点是否被访问过!
int path(int u)
{
int v;
for(v=0;vif(edge[u][v]&&!visited[v])
{
visited[v]=1;
if(cy[v]==-1||path(cy[v]))//如果y集合中的v元素没有匹配或者是v已经匹配,但是从cy[v]中能够找到一条增广路
{
cx[u]=v; //找到增广路,修改匹配M
cy[v]=u;
return 1;
}
}
}
return 0;
}
int maxmatch()
{
int res=0;
memset(cx,0xff,sizeof(cx));//初始值为-1表示两个集合中都没有匹配的元素!
memset(cy,0xff,sizeof(cy));
for(int i=0;i<=nx;i++)
{
if(cx[i]==-1) //还没被匹配,执行内部代码
{
memset(visited,0,sizeof(visitited)); //重置标记为为访问
res+=path(i); //以 i 为起点开始查找增广路,返回true ,匹配数+1
}
}
return res;
}
Hopcroft-Karp算法
太长,不会,日后请自行了解
二分图有下面两个性质:
定理1:最小覆盖数 = 最大匹配数
定理2:最大独立集S 与 最小覆盖集T 互补
算法实现步骤:
定义:用最少的不相交路径覆盖所有顶点。
算法:把原图中的每个点i拆成Xi和Yi,如果有一条有向边i->j,那么就加边Xi-Yj。这样就得到了一个二分图,下面的任务就是求最大匹配,然后最小路径覆盖=原图的节点数-新图最大匹配。
证明见前文。
定义:用最小的可相交路径覆盖所有顶点。
算法:先用floyd求出原图的传递闭包(即连通性),即如果i到j有路,那么就加边i->j。然后就转化成了最小不相交路径覆盖问题。
问题
对于二分图的每条边都有一个权(非负),要求一种完备匹配方案,使得所有匹配边的权和最大,记做最佳(优)完美(备)匹配。(特殊的,当所有边的权为1时,就是最大完美(备)匹配问题)
二分图最大匹配和二分图完美匹配的区别
二分最大匹配:使得匹配中的边数量不小于任何其他的匹配。
二分完备匹配:使得图中所有点出现在该匹配中。二分图的带权匹配与二分图的最佳匹配的区别
二分图的带权匹配:求出一个匹配集合,使得集合中边的权值之和最大或最小。
二分图的最佳匹配:匹配必须为完备匹配,在此基础上,才要求匹配的边权值之和最大或最小。
二分图的带权匹配与最佳匹配不等价,也不互相包含。Kuhn-Munkers算法求二分图的最佳匹配
Kuhn-Munkers算法可以实现为O(N^3)的时间复杂度。
这算法太神 / 我 / 不 / 会,你们暂时用不到 / 我 / 到 / 现 / 在 / 都 / 没 / 用 / 到 / 过,可以自行了解。
推荐网址
http://philoscience.iteye.com/blog/1754498
http://www.linuxidc.com/Linux/2013-02/79458p2.htm
例题:已知班级有g个女孩和b个男孩,所有女生之间都相互认识,所有男生之间也相互认识,给出m对关系表示哪个女孩与哪个男孩认识。现在要选择一些学生来组成一个团,使得里面所有人都认识,求此团最大人数。
定理:
原图的最大团=补图的最大独立集
原图的最大独立集=补图的最大团。
由于这个题的补图显然是一个二分图,而二分图的补图的最大独立集可以由匈牙利算法求的,所以该题的最大团问题可以转化成补图的最大独立集来做。
推荐网址
http://www.cnblogs.com/pushing-my-way/archive/2012/08/09/2629700.html
http://www.cnblogs.com/zhj5chengfeng/archive/2013/07/29/3224092.html