KM演算法原理 證明

2022-08-27 02:21:10 字數 3080 閱讀 9650

blog:

匈牙利演算法為基礎,改善後用於求解帶權二分圖的求最佳匹配問題

帶權二分圖的邊權重和最大匹配,如下圖所示,最大和為102

帶權二分圖的邊權重和最大完備匹配,如下圖所示

顯然,最佳匹配和最大權匹配並不一致,但如果把剩下的邊補上,並且設定權重為零,那麼二者可以統一起來

下面講的km演算法是用來求最佳匹配,而非最大權匹配。

km演算法是一種計算機演算法,功能是求完備匹配下的最大權匹配。

如果不存在完備匹配,那麼演算法會求最大匹配,如果最大匹配有多種,那麼結果是最大匹配中權重和最大的。

在乙個二分圖內,左頂點為x,右頂點為y,現對於每組左右連線xiyj有權,求最大匹配,並且使得該匹配中所有的和是最大。

該演算法是通過給每個頂點乙個標號(叫做頂標)來把求最大權匹配的問題轉化為求完備匹配的問題的。

設頂點的頂標為的頂標為,頂點的頂標為,頂點與之間的邊權為,在演算法執行過程中,對於圖中的任意一條邊,始終成立。

g當中每一條邊有左右兩個頂標,*相等子圖*就是那些頂標和等於邊權重的邊構成的子圖,如下圖綠色加粗線構成相等子圖

km演算法的正確性基於以下的定理:

定理:若二分圖中,,並且存在某個相等子圖有完備匹配,那麼這個完備匹配就是二分圖的最大權匹配。

證明:因為這個完備匹配存在於相等子圖中,因此,這個匹配所有邊都滿足:,同時由於完備匹配包含所有的頂點,因此這個屬於相等子圖的完備匹配的總權重等於所有頂標的和。

如果這個二分圖存在另外乙個完備匹配,如果它不完全屬於相等子圖,即存在某條邊,那麼該匹配的權重和就小於所有頂標的和,即小於上述屬於相等子圖的完備匹配的權重和。

首先選擇頂點數較少的為x部,初始時對x部的每乙個頂點設定頂標,頂標的值為該點關聯的最大邊的權值,y部的頂點頂標為0。

對於x部中的每個頂點,在相等子圖中利用匈牙利演算法找一條增廣路徑,如果沒有找到,則修改頂標,擴大相等子圖,繼續找增廣路徑。當每個點都找到增廣路徑時,此時意味著每個點都在匹配中,即找到了二分圖的完備匹配。該完備匹配是最大權重的完備匹配,即為二分圖的最佳匹配。

匈牙利演算法對左邊第乙個頂點,在相等子圖中進行增廣路徑搜尋,找到路徑1-c後進行匹配增廣操作,如下圖所示

回答第乙個問題,需要理解如何在保持相等子圖原來的邊符合相等子圖要求的同時,讓新加的邊也滿足相等子圖的要求。

那麼在增廣路徑搜尋時,我們知道,如果下面這些紫色邊任意一條加入相等子圖後,都可以在相等子圖中使用匈牙利演算法找到一條增廣路徑2-a(or 2-b or 2-c-1-a):

km演算法選擇上述三條紫色邊中,頂標和與邊權重差值最小的邊1-a或者2-a,以該最小差值為d

這裡有乙個問題就是為什麼最小那個?首先比這更小了就不能擴大相等子圖了,但是如果大了,就不能保證

總是成立了。比如上圖選擇了2-b邊的差值2,那麼修改頂標值後,1-a有

。而km演算法中需要修改的頂標,是那些在匈牙利演算法增廣路徑搜尋時,產生一棵交錯樹,為了保證

總是成立,交錯樹上所有的頂標都要參與修改。

比如在如上第二個頂點搜尋增廣路徑時,產生如下圖所示的橙色頂標集合:

修改頂標後產生如下圖所示的結果:

在該相等子圖上以頂點2為開始點,搜尋增廣路徑2-a(or 2-c-1-a),進行增廣操作:

同樣對左邊第三個點:

另外乙個問題是為什麼修改橙色頂標而不去修改頂標a(找到最小差對應的邊的右邊頂標)?修改頂標a的值為-1,那麼邊1-a也可以加入相等子圖了。問題就在於能不能保證總是成立,如下圖所示結果,修改頂標a,邊3-a就不滿足該條件了。除非在修改頂標a的同時,增加頂標3的值,但是需要修改的頂標集合需要額外的搜尋演算法,而修改橙色頂標所需要的交錯樹在增廣路徑搜尋時可以一併產生。

#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 3;

const int inf = 0x3f3f3f3f;

int wx[maxn], wy[maxn];//每個點的頂標值(需要根據二分圖處理出來)

int cx[maxn], cy[maxn];//每個點所匹配的點

int visx[maxn], visy[maxn];//每個點是否加入增廣路

int cntx=maxn, cnty=maxn;//分別是x和y的點數

//int map[maxn][maxn] = ,, };//二分圖邊的權值

int map[maxn][maxn] = ,, };//二分圖邊的權值

int minz;//邊權和頂標最小的差值

bool dfs(int u)//進入dfs的都是x部的點

}else if (t > 0)//此處t一定是大於0,因為頂標之和一定》=邊權

}} return false;}

int km()

wx[i] = max(wx[i], map[i][j]);

} }for (int i = 0; i < cntx; i++)//列舉x部的點 }

int ans = 0;//二分圖最優匹配權值

for (int i = 0; i < cntx; i++)

if (cx[i] != -1)ans += map[i][cx[i]];

return ans;

}int n, k;

int main()

匈牙利演算法 KM演算法

匈牙利演算法 求最大匹配,那麼我們希望每乙個在左邊的點都盡量找到右邊的乙個點和它匹配。我們依次列舉左邊的點x的所有出邊指向的點y,若y之前沒有被匹配,那麼 x,y 就是一對合法的匹配,我們將匹配數加一,否則我們試圖給原來匹配y的x 重新找乙個匹配,如果x 匹配成功,那麼 x,y 就可以新增為一對合法...

匈牙利演算法,KM演算法

bool find int x return false 主程式 for i 1 i n i include include include include include include include include include include include include include...

KM演算法板子

原題hdu2255 其實在求最大 最小的時候只要用乙個模板就行了,把邊的權值去相反數即可得到另外乙個.求結果的時候再去相反數即可 最大最小有一些地方不同。include include include include 赤裸裸的模板啊。const int maxn 301 const int inf ...