KM算法理解

来源:互联网 发布:饥荒 熔炉 知乎 编辑:程序博客网 时间:2024/06/08 16:59
算法目的:有一个带权二分图,求最大权匹配。O(n^3)

KM算法是通过给每个顶点一个标号(叫做顶标)来把求最大权匹配的问题转化为求完备匹配的问题的。设顶点Xi的顶标为A[i],顶点Yi的顶标为B [i],顶点Xi与Yj之间的边权为w[i,j]。在算法执行过程中的任一时刻,对于任一条边(i,j),A[i]+B[j]>=w[i,j]始终 成立。KM算法的正确性基于以下定理:
  若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做等价子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配。

定理:设 L 是二部图 G 的可行顶标。若 L 等价子图 G有完备匹配 M,则 M 是 G 的最大权匹配。
证明:由于 GL 是 G 的等价子图,M 是 GL 的完美匹配,所以,M 也是 G  的完美匹配。以由于对于匹配 M 的每条边 e ,都有 e∈ E( GL ),而且 M 中每条边覆盖每个顶点正好一次,所以
W( M )= å W(e), e∈ M = å L(x), x∈ V
另一方面,对于 G 的任何完美匹配 M' 有
W( M' )= å W(e), e∈ M' <= å L(x), x∈ V
于是 W( M )>= W( M' ),即 M 是 G 的最优匹配。


KuhnMunkras算法(即KM算法)流程:

    (1)  初始化可行顶标的值

    (2)  用匈牙利算法寻找完备匹配

    (3)  若未找到完备匹配则修改可行顶标的值

    (4)  重复(2)(3)直到找到相等子图的完备匹配为止


细节的理解:
1.使用匈牙利算法是注意匹配条件:x[u]+y[v]=w[u,v]
2.如何修改顶标扩大子图:
  <1>需要修改顶标的条件:当想要继续扩大二分图的交替路时,发现已经无法继续扩大时;
  <2>无法继续扩大的原因:x[u]+y[v]>w[u,v],所以需要修改顶标;
  <3>实现:把x[u]减小就好了。那么减小多少,会不会对其它点造成影响?
      解释:当u这个点找交替路的时候,如果找不到了,那么就可以得到一个交错树(意思就是当匈牙利增加交替路的时候在左右集合访问过的点),那么在交错树里面的左集合X的点和右集合Y的点一定是构成了完备匹配,即x[u]+y[v]=w[u,v] u,v∈交错树点集。对于一般u,v有如下讨论:
             u,v在交错树内,减小了x[u],为了使x[u]+y[v]和原来的值w[u,v]依旧相等,则y[v]就要加上x[u]减小的值tmp(下面就用tmp表示)
             u在交错树内,v不在,x[u]减小tmp,使得x[u]+y[v]减小tmp,那么其就有可能等于w[u,v]
             u不在交错树内,v在,y[v]增加了tmp,使得x[u]+y[v]>w[u,v],没有变化符合条件
             u,v都不在交错树内,不用变
     所以最后的结论是:如果u在交错树内x[u]减小tmp,如果v在交错树内y[v]增加tmp。这样对其他的情况也不会产生影响。其实x[u]的减少就是在给其他的不在交错树内的点v机会,让其增加到交错树内。
  <4>确定tmp值:tmp当然是越小越好,但是也不用从-inf枚举,那样很无聊。只要让tmp为|所有u在交错树,v不在交错树的边的两个顶标减去边的权值中|最小的值就好了(这里的“|”是断句不是什么符号)。
  <5>slack数组优化:只讲一点:为什么对于v不在交错树的点每一次更行slack要减去tmp?
      解释:因为slack[v]表示u在交错树内,v不在交错树内,x[u]+y[v]-w[u,v]的最小值,因为之前x[u]被减少了tmp,导致x[u]+y[v]-w[u,v]减小,所以这里要减去tmp。



1 0
原创粉丝点击