二分图
0x00 简介
- 什么是二分图?
- 顾名思义,就是能分成两个部分的图
- 如果把这两部分分别叫做{U},{V},我们规定,如果存在一种U、V的划分,使所有图中的边<u,v>,不存在u,v在同一个集合(同时在{U}或者{V}),那么这个图就是二分图
- 这个性质有什么用呢?
- 我们发现可以把一个集合摆在左边,另一个集合摆在右边,然后所有原图中的边都是从左边连到右边,没有左-左和右-右的边
- 然后我们就可以干一些神奇的事
0x01 最大匹配
- 一个班级里有一些男女同学,一些同学之间了美好的情感,我们希望找一个最大匹配,就是希望找到最多对有好感的同学,把他们两两配对且没有冲突
- 我们发现男女同学构成的关系网是一张二分图(没有男-男,女-女的边)
- 于是乎问题就变成了一个二分图最大匹配问题,一个二分图中不存在奇环(简单可证),所以我们有神奇的办法解决这个问题
网络流!
- 从S向男孩子连容量为1的边,从男孩子向他喜欢的女孩子连容量为1的边,从女孩子向T连容量为1的边
- 求最大流,正确性很显然
- 就是常数有点大
匈牙利算法
-
我们发现,如果我们从一个没有妹子的男生出发,走一条男-女-男-女-男-女……的链,并且匹配边与不匹配边交错,最后以一个没匹配到的妹子结束
-
像这样
-
男 --- 不匹配 --- 女 --- 匹配 --- 男 --- 不匹配 --- 女
-
然后我们把路径上所有的匹配与不匹配取反
-
变成这样
-
男 --- 匹配 --- 女 --- 不匹配 --- 男 --- 匹配 --- 女
-
我们发现,这样没有影响匹配不冲突的性质,并且总的匹配数量+1
-
我们就可以不断的重复这个过程,不断地使匹配数+1,直到找不到这样的链为止
-
这样的链叫做增广路
HK算法
- 全名叫什么我也记不得了
- 这是一个对匈牙利算法的优化
- 我们发现,一次DFS找增广路的时间和增广路的长度息息相关,这和网络流是类似的(我们也希望找一条长度最短的增广路)
- 那我们怎么优化网络流呢?
- Dinic!对顶点进行距离标号,只允许距离+1的增广
- 这里也可以类比这样的做法,对二分图进行距离标号,只允许距离+1的增广
- 然后跑匈牙利就可以啦!跑是最快的,比Dinic求最大匹配快的多
0x02 最大权完备匹配
- 有的时候,同学们之间的情感是不等的,一些同学们之间君子之交,而另一些同学们干柴烈火
- 然后我们希望找一种最干柴烈火的配对方案
- 这就需要最大权匹配
费用流!
- 从S向男孩子连容量为1费用为0的边,从男孩子向他喜欢的女孩子连容量为1费用为这个配对的权值的边,从女孩子向T连容量为1费用为0的边
- 求最大费用最大流,正确性很显然
- 就是常数有点大
KM算法
- KM算法要求一张完全二分图!!!如果不是完全二分图得补成完全二分图!!!
- 我们考虑给男孩子和女孩子都维护一个期望值,只有一组男女配对满足:男孩子的期望+女孩子的期望 == 这组配对的权值 ,我们才认可这对配对
- 并且时刻保持对于所有的配对,都有 男孩子的期望+女孩子的期望 >= 这组配对的权值
- 这样如果我们对于期望进行一些调整,并且满足上面两个性质的前提下,找到了一种完备匹配(所有人都匹配上了),那么这种匹配是权值最大的
- 显然此时的匹配权值就是男女同学的期望值之和,考虑到这一点,KM算法的正确性就不难理解了
- 正确性解释:我们考虑二分图的任何一个匹配,它的权值可能大于任意时刻的期望值之和么?
- 不可能,显然任何一组匹配里每个男孩和女孩都只出现了一次,因此由第二条性质我们可以推导出 (sum)男孩子的期望+(sum)女孩子的期望 >= 任何一组匹配权值
- 所以如果我们能够取等了,那么此时就是最大匹配
- 那么我们如何修改期望呢?
- 考虑某个时刻,如果我们发现此时的期望太高,不能为一个男孩子找到配对,那么我们要考虑降低期望
- 首先,本来能认可的配对显然还需要继续认可,然后我们应该新加入一些认可的匹配。由于不能删去本来认可的匹配,我们发现本来认可的匹配两边一定是一边加一边减,而且数值相同。我们考虑这个男孩子匹配的过程,一定是由于他所有喜欢的都女孩子被另一些男孩子抢了,并且找不到增广路,所以才会导致匹配不存在。
- 那我们要让期望降低多少,才能加入一个配对呢?
- 我们考虑找增广路的过程,一定有某个时刻一个没匹配上的男孩子被拒绝了,原因是配对权值不等于期望之和,那么这个男孩子要降低一些期望,才能加入一些配对,要降低的最少期望等于他所有被拒绝的经历中,离目标最近的那一个,设这次的差为delta
- 我们发现找增广路的过程中一定是左右左右左交替,并且以左开始,以左结束,死在一个找不到增广路的男孩子身上,这样的话我们取所有男孩子的delta的最小值d,把增广路上所有男孩子的期望降低d,所有女孩子的期望增加d
- 这样,所有原来在匹配中的边还在匹配里,并且由于左边的点比较多,总的期望下降了一点
- 不断重复这个过程,直到找到完备匹配
- 具体实现看代码
- 一个优化!将原来的匈牙利DFS找增广路改成BFS,不然会被卡掉!!
Extra
- 如果我们要求非完全二分图最大权匹配,不要求全部匹配上呢?
- 对于费用流做法,只要增广的费用小于零就停止不做了
- 对于KM做法,补上一些权值为0的配对补成完全图就可以了
- 如果我们要求非完全二分图最大权匹配,要求全部匹配上呢?
- 对于费用流做法,正常搞就可以了
- 对于KM做法,补上一些权值为-INF的配对补成完全图