km演算法的個人理解

2022-09-15 18:42:11 字數 2949 閱讀 8721

首先相對於上個blog講的匈牙利演算法用於解決無權二分圖的最佳匹配,km演算法則是在匈牙利演算法基礎上更進一層的,每條邊增加了權值後,真的開始看時有些無厘頭,覺得沒有什麼好方法,但兩位牛人kuhn-munkras在2023年提出的,而匈牙利演算法是在2023年提出的,

終於翻了圖書館3本書的講解和無數網上牛人的講解,終於看懂的,這當然是後話.

首先km演算法是在匈牙利演算法基礎上執行的,本質上km演算法大致意思就是先將x集合中每條邊連線上其所能連線的最大權值邊,如果沒有衝突,當然是正確的,有的話,也別急,現在我們要做的是將這個ans逐漸縮小,然後將衝突的邊調開,直到滿足二分圖完備匹配(這個地方用匈牙利演算法求最大匹配,若最大匹配是完備匹配,就滿足)的時候,此時便是正確的答案.

至於如何將衝突的邊進行調整,才能使ans縮小得剛好,又能夠使得x集合能夠找到各自的y取得最大權值,因此我們給每個x,y集合上的點引入乙個可行頂標lx,ly,當初就是不明白為什麼需要引入這兩個頂標才搞了很久,顧名思義,可行頂標就是用來判斷當前點是否可行,km演算法中即根據lx[i]+ly[j]的大小判斷是否i,j能夠連線.

可能我們先來證明乙個定理會更容易理解km演算法:

w[i,j]表示i到j的權值,設w=(wij)(i∈x,j∈y),其中排列,使最大匹配m=(wij)(其中(in,jkn)連線) ,存在,,滿足lx[i]+ly[j]>=w[i,j],且其中lx[in]+ly[jkn]=w[in,jn],     最佳匹配的權值和max(sigma(wij))=min(sigma(lx)+sigma(ly))

舉個例子好理解:

一開始我們令所有x集合lx[i]=max(w[i,j]),ly[j]=0,則保證lx[i]+ly[j]>=w[i,j],然後我們通過乙個**來表示x和y之間的關係,

則lx[1]=3lx[2]=2 lx[3]=2 ly=0

然後做乙個**表示lx[i]+ly[j]-w[i,j]

lx[i]-ly[j]-w[i,j]     

j1j2

j3i1

i2i3

因為要保證lx[i]+ly[j]>=w[i,j]所以我們只匹配lx[i]+ly[j]=w[i,j]的邊,即其他lx[i]+ly[j]>w[i,j]的邊先去除.

說明:仔細想想,當前這個情況若滿足每個0都在不同行不同列,是不是當前這個情況就是最佳匹配,因為現在每個x都選到了最大的y,顯然沒有比這個更大的匹配了,不過情況比這個複雜些,其中i1,i2都和j1匹配,產生衝突,所以我們應該修正.

是不是有點感覺了,仔細想想,現在我們應該增大0的個數使得存在不同行不同列的0有n個,因為0即表示可以匹配,所以是不是感覺到可以使用匈牙利演算法來找出不同行不同列0的個數,只要等於n即表示當前這個ans=max(sigma(wij))是最優的.

不過當前情況不符合匹配,所以我們要適當縮小ans,使得ans縮小到下乙個狀態,在這個狀態中至少要多出乙個0,而且其他邊的lx,ly不要影響這些的狀態,

因此要得到至少多出乙個0,我們得將**中最小的正整數min=(1,1,1)=1減掉,

現在我們是到i2時發現衝突,因此我們得調整lx,ly,然後重新用匈牙利演算法匹配,

這樣我們也就是要將i1或者i2與其他的j匹配,所以我們將sx上的點即i1,i2的lx下調1,然後將sy的點即j1的ly上調1,

這樣的話我們得到

lx[1]=2lx[2]=1 lx[3]=2 ly[1]=1 ly[2]=0 ly[3]=0

lx[i]-ly[j]-w[i,j]     

j1j2

j3i1

i2i3

多出乙個0,現在匈牙利演算法計算時就滿足完備匹配了ok

我搞的這個資料不太好,一步到位…,不過足以說明了

然後說明一下為什麼這樣調保證即使還得繼續調整也是正確:每次有匹配衝突時,表示x集合上有一點p無法再插入sx中,我們暫時把它當做入了sx,我們得為他或者其他入交錯圖的x找到乙個匹配,p才能真正入sx. 但是原來的0(原來的邊)不能被刪除,故我們將sy中的點ly+min這樣就保證原來的lx+ly=w,原來的邊依舊可以用

其中因為|sx|=|sy|+1;sigma(lx)+sigma(ly)比之前減少了min*(|sx|-|sy|)=min

也就是:

對於sx,sy上點:lx-min+ly+min=lx+ly不變

對於sx,非sy上點:lx-min+ly對於非sx,sy上點:lx+ly+min>lx+ly又lx+ly>=w,故lx+ly+min依舊滿足》=w

對於非sx,非sy上點:無影響

將上點lx[i]均-min不是就使得在與之間至少出現一條使得lx[i]+ly[j]=w[i,j],即多出至少一條邊,從上述**形式即多出乙個0,而且我們是將下乙個多出0的情況找到,故這滿足最佳匹配.

因此只要經過有限次的重複上述步驟可達到求得min(sigma(lx)+sigma(ly))

即ans

補上**:

#include#include#includeusing namespace std;

int lx[200],ly[200],w[200][200],pre[200];

int n,ans,mi;

bool sx[200],sy[200];

bool path(int p)

}return 0;

}int main()

for(i=1;i<=n;i++){

memset(sx,0,sizeof(sx));

memset(sy,0,sizeof(sy));

while (!path(i)){

mi=2000000000;

for(j=1;j<=n;j++)

for(k=1;k<=n;k++)

if (sx[j]&&!sy[k]){

if (lx[j]+ly[k]-w[j][k]

KM演算法理解

二分圖帶權匹配與最佳匹配 什麼是二分圖的帶權匹配?二分圖的帶權匹配就是求出乙個匹配集合,使得集合中邊的權值之和最大或最小。而二分圖的最佳匹配則一定為完備匹配,在此基礎上,才要求匹配的邊權值之和最大或最小。二分圖的帶權匹配與最佳匹配不等價,也不互相包含。我們可以使用km演算法實現求二分圖的最佳匹配。方...

關於km演算法 最佳匹配 的個人總結 模板

km演算法具體講解請看 本文只是模板 include include includeconst int inf 0x3f3f3f3f using namespace std int book 1001 記錄當前男生是否已經被哪個女生選中,單身為0 int used boy 1001 記錄哪些男生在這...

KM演算法的介紹

km演算法是通過給每個頂點乙個標號 叫做頂標 來把求最大權匹配的問題轉化為求完備匹配的問題的。設頂點xi的頂標為a i 頂點yj的頂標為b j 頂點xi與yj之間的邊權為w i,j 在演算法執行過程中的任一時刻,對於任一條邊 i,j a i b j w i,j 始終成立。km演算法的正確性基於以下定...