二分匹配_最佳匹配KM算法

二分圖最佳匹配有匹配後總權值最大和最小兩種,求最佳匹配的一個有效算法是KM算法。KM算法很複雜很費解。現在只能總結步驟。

KM算法步驟( 以下有層次關係,㈠ > 1 > (1) > > Ⅰ

(一)  建圖:所有點分爲兩部分,一部分屬於L端,一部分屬於R端,兩端的點各有n個,現在要爲L端的所有點在R端的點中找它們的匹配,使最後總權值最大或最小,設有一條邊聯通Li點與Rj點,權值爲w[i][j],設二維數組gragh_m保存圖,graph_m[i][j]= w[i][j]

(二)  爲每個點設一個頂標,L端的爲plR端的爲pr,將pr的全賦爲0pl全賦爲與這個點聯通的權值最大的邊的權值,例如與L端第i個聯通的最大權值的邊的權值爲m,則pl[i]=m

(三)  用一個循環枚舉L中的每個點,爲每個點在R中找其最佳匹配

1.設一輔助數組slack(可在全局定義)大小爲n,slack全賦爲MAX_INT(無窮大)。

2、用一個死循環爲L中的每個點找匹配,直到找到這個匹配時候break掉此循環,

⑴定義兩個數組vl,vr,全賦爲0,分別表示L中的某個點沒有被訪問過和R中的某個點沒有被需要過(需要表示R中的某個點滿足L中的某個點的最佳匹配要求,但被需要不表示最後能肯定配到它)

⑵以當前的爲其找匹配的點作爲實參調用匹配函數match,這裏假定這個點位置爲pos

   match 函數體如下:

     vl[pos]賦爲1(訪問過

     用個循環枚舉R中的每個點,設當前點爲j,如果這個點還沒有被需要過(vr[j]==0)則執行:定義變量val=pl[pos]+pr[j]-graph_m[pos][j];

如果val==0(滿足匹配條件)

{

   .vr[j]=1;

.如果pre[j]==-1或者matchpre[j]==1(pre[j]表示L中與Rj點的匹配點),則pre[j]=pos,返回真。

}

否則如果(val>0

{

如果val<slack[j],slack[j]=val;

}

                 ③返回假。

         ⑶.如果match返回真,break當前循環。

         ⑷定義變量d=MAX_INT,枚舉R中每個點,如果vr[j]==0(沒被訪問過)並且slack[j]<val,則d賦值爲slack[kj]

               ⑸枚舉L中每個點和R中每個點,假設當前點爲j,如果vl[j]=1,pl-=d;如果vr[j]==1,pr[j]+=d;

3.將匹配後每個匹配對的權值加起來。

 

      KM算法C++模板,模板的註釋爲上面所描述的步驟

最佳匹配題目

POJ2195 這裏求的是最小匹配,模板的返回值要變成負的,代碼

            

 

發佈了33 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章