匹配算法·温故知新——「一般图的最大(基数)匹配」

启发

上文介绍了二分图的最大匹配,自然而然地想到,这个算法能否推广到一般图?

在一般图中,找到一个matching,使得它包含的边数最多。

我们发现上文算法中的基本概念augmenting path并非依赖于二分图的性质,这是一个好消息。
那么二分图特殊在哪儿呢?

G为二分图的充要条件是|G|>2且图中没有奇长度的环。

那么这个性质有什么影响呢?能否在原算法的基础上通过修改解决这个问题呢?如果不能,又要退回到更基本的概念和想法上。
这便是算法延展的一般思路。

症结

我们“照葫芦画瓢”,继续使用ST标号的方法,只不过这次没有boy和girl的说法了。得到如下标号规则:
1. 如果xS, y is free(x,y)E,(x,y)matching,那么给 y标上T。
2. 如果 yT, x is free,(x,y)E,(x,y)matching,那么给 x标上S。
好像没什么不妥,顺着这个思路继续模仿:

  1. 清空标记,将所有单身的点标成S,并从他们开始搜索。
  2. 搜索x时,遍历相邻的点y,根据上面的规则给y标号,继续搜索y。
  3. 若搜索到单身的点,则证明从起始点到搜到的单身点有一条augmenting path,增广并进入下一个阶段。
  4. 若3不能满足,则证明已经得到最大匹配,退出。

等等,哪里不对。怎么会这么简单?
当然不可能这么简单。原因在2中按照上述规则给y标号时,存在标号冲突。
情况1:先被标成T,后被标成S。
这种情况只会在一对配偶都被标成T,之后其中一个点开始扩展的时候发生冲突。考虑到标成T的点在扩展的时候,根据规则2,只能去标它的配偶点且标成S,我们可以在实现的时候,每标到一个T,立刻标记它的配偶点为S,从而消除这种冲突
情况2:先被标成S,后被标成T。
首先如果两边来自不同单身点的搜索,则找到一条增广路,但来自同一个单身点怎么办?想一下匈牙利算法的实现,我们每次只扩展一个单身点,这种方法下,一旦出现冲突,一定是来自同一个单身点的扩展。
这种情况不能避免,处理方法是这个算法的核心所在——缩点
我们来看论文中的一幅图。
匹配算法·温故知新——「一般图的最大(基数)匹配」_第1张图片
在这幅图中,i在搜到相邻的j点时,j已经标为S,但此时根据规则,若j空闲应该标T。
我们仔细观察后发现,找到搜索树的最近公共祖先后,整个结构形成一个奇环,成为带花树的花苞(blossom)。保证奇环内匹配数最多的情况下,只能有一个点向外匹配,且无论它最初被标成S或T。这个性质像极了一个S点!
所以我们将图中圆圈内的这个奇环缩点,继续操作就可以了。注意每个stage要重新拆开哦!

实现

这个算法说起来很容易,但是实现起来比较困难,特别是缩点之后在找augmenting path时还有拆开,而且可能多重缩点。
但暴力地写法还是很容易的,搜索顺序用DFS比较好,不用求搜索树的LCA,老老实实创建新点,把环中的边都加进去云云。时间复杂度O(n4)
考虑上述瓶颈,主要在每次缩点都要枚举一遍边,以及判断两个点是否在同一个blossom中。前者可以用链表存边解决,后者可以用并查集解决。但是层层剥离blossom求augmenting path的实现难度依然很大。我建议另建一棵树维护blossom的内外结构。时间复杂度O(n(m+n))
另一种论文上提到的方法是使用BFS的顺序,blossom不真正缩点,而是用一种巧妙的双向链表把边连起来,再把blossom中所有点加入搜索队列。时间复杂度O(n3)。//貌似网上大多采用这种实现,而且还是本学期图论助教最先实现的。

你可能感兴趣的:(算法手札)