先给出一些图论的定义
(这部分其实也可以不看,第二个大标题开始讲正文)
匹配
给出图G = (V,E),我们取E的一个子集M,其中M中任意两条边没有公共顶点,我们则称M中的边为匹配边,同时将M中的点叫做匹配点。
(剩下的叫未匹配边、未匹配点)
极大匹配
在一个匹配的基础上,我们可以扩大匹配(这个就是匈牙利算法的精髓,一会讲),当扩大到最大,我们就说这是一个极大匹配。
最大匹配
在极大匹配中,有的匹配边数会比其他的多一点,所以我们把最大的叫做最大匹配。
完美匹配
这个就更牛皮了,M连接的所有顶点刚好为V。
二分图
一个图能被划分成两部分,使得任意一条边的两个顶点分别在两个部分中。
交错路径和增广路径
交错路径顾名思义,就是相邻两条边性质不同。
这里我们取非匹配边-匹配边-非匹配边……的路径为交错路径;
增广路径则是从一个非匹配点出发,走交错路径到另一个非匹配点(保证了两边的边为非匹配边)
推论
-
增广路径的边数一定为奇数,且两边的边属于非匹配边
-
对于一个增广路径,我们可以将M取反(匹配边改为非匹配边),得到一个更大的M’,也就是匹配的扩大。(图中红色边为匹配边)
-
M为G的最大匹配等价于不存在M的增广路径
匈牙利算法
我们来讨论一个问题,就是员工和任务的分配问题。
这次不是讨论最小代价&树搜索了,而是有的活有的人干不了。
图中左边为活动,右边为人,很明显这是一个二分图
开始我们给5分配活动2,6分配活动3,7分配活动4,到了老八,老八一看不行啊,我只能干活动4啊!
7想了想,自己和老八抢活干总感觉不太对劲,就改成了活动1,这下大家都有事情做了。(老八狂喜
然后,我们就得到了一个匹配扩张算法。
???
首先,我们给出了一个小的匹配(5-2、6-3、7-4),没有包含所有人,也就是说明不是最大匹配,然后我们要进行扩张。
将原来的4-7,首先我们有非匹配边1-7,然后是匹配边4-7,还有非匹配边4-8,然后就可以将其进行扩张,得到匹配边1-7和4-8,非匹配边4-7。
简单一点就是有的人能干很多活,需要给菜鸡让地方。就是一个匹配扩张的问题,也是匈牙利算法的核心。
举一个例子
有m个小朋友,还有n=>m块饼干,饼干有一个大小,孩子对饼干的大小有需求,我们需要给每一个孩子分配一个满足其胃口的饼干。
如果是胃口小的孩子,稍微大一点的饼干就行,给一个超级大的也行,就属于上面的5,什么都能干;
如果是胃口大的孩子,只能和上面的老八一样了(我没骂人啊)。
然后我们就可以使用匈牙利算法来解决问题了。
但是,我们还有一个办法,直接贪心啊。先给胃口大的孩子分配最大的饼干,然后依次。