KM算法求带权二分图的完美匹配

因为这个算法不太好理解,所以也是验证一下自己有没有学会。

首先在学习这个算法之前,需要先学会使用匈牙利算法求二分图的最大匹配。

这个算法首先定义了一个概念:可行顶标。我们也可以这么理解,这个二分图是边带权的二分图,我们同时给点也定义一个权重。每个点的权重是这样初始化的,对于在x集合中的点,找到与这个点相连的所有边,取最大边权更新这个点的权重。对于在y集合中的点,权值都初始化为0。假设可行顶标用函数L表示。

对于集合x中的第i条边,其可行顶标为L[i],对于集合y中的第j条边,其可行顶标为L[j],在算法执行过程中的任意一个时刻,我们都有这样的结论:L[i]+L[j]>=w[i][j]  (w是边权,很明显在按照上述方式,初始化顶标后这个结论是成立的,在算法运行的过程中其实它也是成立的,这个东西有什么用,暂时可以不用管)

算法终止的条件是二分图中所有满足L[i]+L[j]==w[i][j]的边构成的子图(这样的子图叫做相等子图)具有完备匹配,那么这个匹配就是最大权匹配。(完备匹配的概念为顶点数较小的那个集合里所有的点都有了匹配)。

上述的算法终止条件不难理解。因为根据我们提过的一个结论L[i]+L[j]>=w[i][j],则寻求的另一完备匹配的权和必然小于所有顶标之和,比等于完备匹配这个结果要差,所以必然不是我们需要的结果。

算法接下来以修改顶标的方式扩大相等子图,使相等子图具有完备匹配为止。

可以想象一下当我们扩大相等子图的时候,对于一个集合x中的顶点,我们在y中无法找到匹配,无法找到匹配的原因是2个点顶标之和大于边权而不等于边权。这时候我们需要做的是修改顶标。对于集合x中的所有点,我们让已经匹配的点减去一个d,同时让集合y中的所有已经匹配的点加上一个d。

下面证明修改顶标的正确性。对于相等子图中已经存在的边,这么做并没有影响(一个点顶标加,一个减),对于一条边,如果它的2个顶点都不在相等子图中,这样的修改也对它没有影响。对于一个点属于x集合已匹配的点,而一个点属于y集合未匹配的点的边,这条边所连接的在x集合中的点顶标变小了,而在y集合中的点顶标没有变,所以我们有可能做到L[i]+L[j]==w[i][j],因此相等子图有可能扩大了。最后一种情况是x集合中的点顶标没变,y集合中的点顶标变大,这种边,它原来就不在相等子图中,现在更加不在相等子图中了。

下面再讨论这个d怎么找。不难发现d=min(L(i)+L(j)-w[i][j] ),如果d比这个值小,不会有新的边加入,如果d比这个值大,会破坏已经匹配了的边。朴素做法计算这个d是O(N^4)复杂度,优化的做法是给集合y中的每一个点定义松弛量slack(j)=min(L(i)+L(j)-w[i][j]),那么d的计算变成d=min(slack(j)), 总时间复杂度可以降成O(N^3),这里就不证明这个slack的应用了。

综上,KM算法结束。

猜你喜欢

转载自blog.csdn.net/zero___zero/article/details/81395533
今日推荐