求最大權二分匹配的KM演算法

2021-05-05 05:01:33 字數 1038 閱讀 7667

最大權二分匹配問題就是給二分圖的每條邊乙個權值,選擇若干不相交的邊,得到的總權值最大。解決這個問題可以用km演算法。理解km演算法需要首先理解「可行頂標」的概念。可行頂標是指關於二分圖兩邊的每個點的乙個值lx[i]或ly[j],保證對於每條邊w[i][j]都有lx[i]+ly[j]-w[i][j]>=0。如果所有滿足lx[i]+ly[j]==w[i][j]的邊組成的匯出子圖中存在乙個完美匹配,那麼這個完美匹配肯定就是原圖中的最大權匹配。理由很簡單:這個匹配的權值之和恰等於所有頂標的和,由於上面的那個不等式,另外的任何匹配方案的權值和都不會大於所有頂標的和。

但問題是,對於當前的頂標的匯出子圖並不一定存在完美匹配。這時,可以用某種方法對頂標進行調整。調整的方法是:根據最後一次不成功的尋找交錯路的dfs,取所有i被訪問到而j沒被訪問到的邊(i,j)的lx[i]+ly[j]-w[i][j]的最小值d。將交錯樹中的所有左端點的頂標減小d,右端點的頂標增加d。經過這樣的調整以後:原本在匯出子圖裡面的邊,兩邊的頂標都變了,不等式的等號仍然成立,仍然在匯出子圖裡面;原本不在匯出子圖裡面的邊,它的左端點的頂標減小了,右端點的頂標沒有變,而且由於d的定義,不等式仍然成立,所以他就可能進入了匯出子圖里。

初始時隨便指定乙個可行頂標,比如說lx[i]=max,ly[i]=0。然後對每個頂點進行類似hungary演算法的find過程,如果某次find沒有成功,則按照這次find訪問到的點對可行頂標進行上述調整。這樣就可以逐步找到完美匹配了。

值得注意的一點是,按照上述d的定義去求d的話需要o(n^2)的時間,因為d需要被求o(n^2)次,這就成了演算法的瓶頸。可以這樣優化:設slack[j]表示右邊的點j的所有不在匯出子圖的邊對應的lx[i]+ly[j]-w[i][j]的最小值,在find過程中,若某條邊不在匯出子圖中就用它對相應的slack值進行更新。然後求d只要用o(n)的時間找到slack中的最小值就可以了。

如果是求最小權匹配,只需要把那個不等式反一下就行了。演算法需要作出的改變是:lx的初值為所有臨界邊中的最小值,find中t反號。

示例程式(ural 1076):

ural1076.cpp

june 18, 2007 · filed under 程式園

HDU2255二分匹配最大權值

傳說在遙遠的地方有乙個非常富裕的村落,有一天,村長決定進行制度改革 重新分配房子。這可是一件大事,關係到人民的住房問題啊。村里共有n間房間,剛好有n家老百姓,考慮到每家都要有房住 如果有老百姓沒房子住的話,容易引起不安定因素 每家必須分配到一間房子且只能得到一間房子。另一方面,村長和另外的村領導希望...

二分匹配演算法

匈牙利演算法求二分匹配 下 include includeusing namespace std int v 頂點數 vectorg max v 圖的鄰接表表示 int match max v 所匹配的頂點 bool used max v dfs 中用到的訪問標記 向圖中增加一條連線 u 和 v 的...

理解匈牙利演算法求二分匹配

匈牙利演算法是用來求二分圖匹配的演算法,一般有bfs和dfs兩種實現,我一般都是寫的dfs的實現,感覺這個比較好理解,實現也比較簡單。二部圖 若乙個圖的頂點可以劃分到2個集合,使得每個集合內的頂點之間沒有連邊,那麼這個圖就叫做二分圖或二部圖。二分匹配問題 求最大邊無關集。交替鏈 二分圖的一條路徑,路...