km算法学习小记

这个算法其实在学匈牙利算法时就看过了,不过当时没搞懂???
现在一看,其实还挺好理解的。

应用

km算法是求最大权完备匹配,事实上它同时能处理最小权完备匹配(把边权取反)和非完备匹配(添加原本不存在的边且边权赋值为0),另外还在一位神犇的博客里了解到,如果我想要边权之积最大,则每条边权取自然对数,然后求最大和权匹配,求得的结果a再算出e^a就是最大积匹配。至于精度问题则。。。不知所措。

正确性

KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B[i],顶点Xi与Yj之间的边权为w[i,j]。在算法执行过程中的任一时刻,对于任一条边(i,j),A[i]+B[j]>=w[i,j]始终成立,初始A[i]为与xi相连的边的最大边权,B[j]=0。KM算法的正确性基于以下定理:
设 G(V,E) 为二部图, G’(V,E’) 为二部图的子图。如果对于 G’ 中的任何边[x,y]满足, A(x)+ B(y)== Wx,y,我们称 G’(V,E’) 为 G(V,E) 的等价子图或相等子图(是G的生成子图)。
若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。
因为对于二分图的任意一个匹配,如果它包含于相等子图,那么它的边权和等于所有顶点的顶标和;如果它有的边不包含于相等子图,那么它的边权和小于所有顶点的顶标和(即不是最优匹配)。所以相等子图的完备匹配一定是二分图的最大权匹配。
初始时为了使A[ i ]+B[j]>=w[i,j]恒成立,令A[ i ]为所有与顶点Xi关联的边的最大权,B[j]=0。如果当前的相等子图没有完备匹配,就按下面的方法修改顶标以使扩大相等子图,直到相等子图具有完备匹配为止。

**

若求当前相等子图的完全匹配失败了,则必须修改顶标。而此时我们会得到一棵交错树。现在我们把交错树中X顶点的顶标全都减小某个值d,Y顶点的顶标全都增加同一个值d,显然相等子图只有可能被扩大。
而一次修改,至少有一条边进入相等子图,d应该等于:
Min{A[ Xi ]+B[Yj]-w[Xi,Yj] | Xi在交错树中,Yj不在交错树中}。
朴素的做法是O(n^4),主要因为枚举d的复杂度很大,为O(n^2)。
若我们给每个Y顶点一个“松弛量”函数slack,每次开始找增广路时初始化为无穷大。在寻找增广路的过程中,检查边(i,j)时,如果它不在相等子图中,则让slack[j]变成原值与A[ i ]+B[j]-w[i,j]的较小值。这样,在修改顶标时,取所有不在交错树中的Y顶点的slack值中的最小值作为d值即可。但还要注意一点:修改顶标后,要把所有的不在交错树中的Y顶点的slack值都减去d。这样就能做到O(n)找到d,使时间复杂度降到O(n^3)

小结

km算法虽然应用比费用流小,但是编程复杂度低,也便于理解,而且也能为学习费用流做基础,个人感觉还是很有必要学会km算法的。

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