匈牙利算法

因为“趣味算法系列之--匈牙利算法”这篇文章写得相当精彩,本文许多从中借鉴。Blog链接为:http://blog.csdn.net/dark_scope/article/details/8880547

匈牙利算法是一种通过使用增广路径来解决二分图的最大匹配的算法,由匈牙利数学家Edmonds于1965年提出。

1.二分图

设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。一个二分图的例子:

2.最大匹配&完美匹配

在图论中,一个“匹配”(matching)是一个边的集合,其中任意两条边都没有公共顶点。
最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。
完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。

3.交替路&增广路

交替路: 从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边...形成的路径叫交替路。
增广路 :从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路。
注意:把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。

4.思想与算法

思想:看这么一个例子,把左边1,2,3,4和右边a,b,c,d来进行匹配
一开始我们给1分配a,1和a之间连上红线表示建立匹配。
然后接着给2分配b,2和b连上红线表示匹配。
紧接着给3分配,这时候发现a,b已经都有所属了,我们尝试给1重新分配,把原来的分配拆掉,用蓝线表示。
但是很快我们发现1重新分配不了,b已经有所属,那么继续尝试给2重新分配,把原来的分配拆掉,用蓝线表示。2重新分配到c,用红线表示。
这个时候,1可以重新分配到b,用红线表示。
最后,3就可以分配到a,用红线表示。
对于4,由于c已经被分配,而且尝试给其他1,2,3重新分配无法实现,就此结束。

基本原则就是在原有匹配基础上重新分配,看是否可以添加一个新的匹配。

算法:

//代码只是为了表示思路,很多变量声明之类的省略了
public static boolean find(int x,int[] connected,int[] used,int[] partner){
    for(int j=0;j


在OJ实例中经常看到匈牙利算法的影子,如华为OJ的“素数伴侣”,POJ 2536。


你可能感兴趣的:(算法练习)