匈牙利算法是解决寻找二分图最大匹配的。
匈牙利算法(Hungarian Algorithm)是一种组合优化算法(combinatorial optimization algorithm),换句话说就是,在可以接受的损失代价内,去做最大匹配。
1.预备知识
什么是匹配:把想象成3男4女搞对象(无同性恋),连线代表彼此有好感,但最终只能1夫1妻,最终的配对结果连线就是一个匹配。匹配可以是空。
什么是最大匹配:在有好感的基础上,能够最多发展几对。
现在要用匈牙利算法找出最多能发展几对。
匈牙利算法是解决寻找二分图最大匹配的。
例子:
给定2个集合A和B,然后将AB中的元素完成一个连线。
匈牙利算法就是要找到两个集合促成最多的匹配对!最佳媒婆。这里最适合举的例子就是相亲会。集合A代表所有男嘉宾,集合B代表所有女嘉宾。每个男女嘉宾都有自己的心动嘉宾,此为重要前提。通过一个算法,完成最多的牵线。
2.匈牙利算法正文:
2.1 匈牙利算法的矩阵形式
给定n位工人以及n件工作,可以用一个n×n的开销矩阵来表示这一指派问题:
其中a,b,c和d表示工人,下标1,2,3,4表示任务; a3表示工人a被指派完成第3项任务的开销,其余元素以此类推。
Step-1 对开销矩阵的各行进行操作:
找出每一行中值最小的元素,然后把该行所有元素都减去这一最小值
完成后矩阵的每一行至少会出现一个0。假如a1,b4,c2,d3是开销矩阵的最小值,则开销矩阵在完成本项操作后变成
这个矩阵每行都有一个0,而且这些0分布于 不同的列,那么开销最小的指派方案就出来了,就是 a→1,b→4,c→2,d→3。
然而问题一般并没有这么简单,执行完这一步后,开销矩阵中的0元素很可能没有分布于不同的行列(如下面的矩阵中第三列没有0),那么继续进行下一步操作。
Step-2 对开销矩阵的各列进行操作:
找出每一列中值最小的元素,然后把该列所有元素都减去这一最小值
这一步之后,如果0分布于不同的行列,则得到了最优解;如果以每个0为中心画十字(见下图)、被十字覆盖的其余0不再画十字,所有的0都画十字后仍有元素未被覆盖(图中c3),则说明指派未完成,继续进行下一步。
Step-3 用尽量少的横线或竖线覆盖矩阵中的所有0:
假设我们现在要对上面的开销矩阵进行操作。
2.3把任务尽可能多的分配给工人
(1)第一行(表示第一个人工可接受的任务)有一个0,所以把第1项任务分配给工人a。由于第1项任务已经分配出去,所以位于第三行第一列的0不再被考虑。
(2)第二行有一个0,所以把第4项任务分配给工人b。
(3)第三行原本有一个0,但是由于第1项任务已经被分配出去,所以不予以考虑,不能给c分配任务。
(4)第四行有两个未被覆盖的0,但只能给d分配一项任务,另一项未被分配的任务要划掉、本轮不予以考虑。
2.4 用最少的线覆盖所有0
- 标记所有上一步后仍未得到任务的工人(矩阵的行):标记第三行
2. 标记所有刚被标记过的行中0所在的列:标记第一列
- 标记所有刚被标记过的列中0所在的行:标记第一行
- 对仍未得到任务的工人(矩阵的行)重复以上3步
- 在所有标记过的列和未标记的行上画线
经过以上画线操作,所有的0就被以最少的线覆盖了。
Step-4
从上一步中未被覆盖的元素中找到最小值,然后把这些元素都减去最这一小值、给直线交叉点的元素加上这一最小值
被覆盖元素中的最小值实际上是完成所有任务过程中不可避免的开销。
这一步的作用是增加开销矩阵中0的个数,使得任务更易分配。
被覆盖元素中的最小值实际上是完成所有任务过程中不可避免的开销。
这一步的作用是增加开销矩阵中0的个数,使得任务更易分配。
Step-5
重复Step-3和Step-4,直到所有任务都被分配
匈牙利算法路径
匈牙利算法中有个非常非常最重要的概念叫做-交错路径,或者叫交错树,指的同一个东西。交错路径是这样的。现在有一个匹配如图黑线所示
则其交错路径为:
交错路径是对于一个匹配而言的,交错路径的起点和终点必须不是匹配中的点,而且匹配中的边在交错路径中交替出现。
给定一个图:
目标是:尽可能给x中最多的点找到配对。
刚开始,一个匹配都没有,我们随意选取一条边,(x1, y1)这条边,构建最初的匹配出来,结果如下,已经配对的边用粗线标出:
我们给x2添加一个匹配,如下图的(x2, y2)边。
目前来看,一切都很顺利,到这里,我们形成了匹配M,其有(x1, y1), (x2, y2 ) 两条边。
我们现在想给x3匹配一条边,发现它的另一端y1已经被x1占用了,那x3就不高兴了,它就去找y1游说,让y1离开x1。
即将被迫分手的x1很委屈,好在它还有其他的选择,于是 x1 妥协了,准备去找自己看中的y2。
但很快,x1发现 y2 被x2 看中了,它就想啊,y1 抛弃了我,那我就让 y2 主动离开 x2 (很明显,这是个递归的过程)。
x2 该怎么办呢?好在天无绝人之路,它去找了y5。
谢天谢地,y5 还没有名花有主,终于皆大欢喜。
匹配如下:
上面这个争论与妥协的过程中,我们把牵涉到的节点都拿出来:(x3, y1, x1, y2, x2, y5),很明显,这是一条路径P。
而在第二步中,我们已经形成了匹配M,而P呢?还记得增广路径么,我们发现,P原来是M的一条增广路径!
上文已经说过,发现一条增广路径,就意味着一个更大匹配的出现,于是,我们将M中的配对点拆分开,重新组合,得到了一个更大匹配,M1, 其拥有(x3, y1),(x1, y2), (x2, y5)三条边。
而这,就是匈牙利算法的精髓。
同样,x4 , x5 按顺序加入进来,最终会得到本图的最大匹配。
得到这个结果后,我们发现,其实也可以把y4 让给 x6 , 这样x5 就会空置,但并不影响最大匹配的大小。
总结:
-
匈牙利算法寻找最大匹配,就是通过不断寻找原有匹配M的增广路径,因为找到一条M匹配的增广路径,就意味着一个更大的匹配M’ , 其恰好比M 多一条边。
-
对于图来说,最大匹配不是唯一的,但是最大匹配的大小是唯一的。
参考链接:
3. https://blog.csdn.net/u011837761/article/details/52058703
-
https://blog.csdn.net/u011837761/article/details/52058703?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.control
-
https://blog.csdn.net/u013384984/article/details/90718287