KM演算法趣味講解 模板

2021-07-31 04:31:40 字數 3149 閱讀 7538

本文** ,同時也參考了

本文配合該博文服用更佳趣寫演算法系列之--匈牙利演算法

km演算法用來求二分圖最大權完美匹配。km演算法的思路:盡量找最大的邊進行連邊,如果不能則換一條較大的。

現在有n男n女,男生和女生每兩個人之間有好感度,我們希望把他們兩兩配對,並且最後希望好感度和最大。

怎麼選擇最優的配對方法呢?

首先,每個妹子會有乙個期望值(標桿),就是與她有好感度的男生中最大的好感度。男生呢,期望值為0,就是,,,只要有乙個妹子就可以啦,不挑~~

這樣,我們把每個人的期望值標出來。

然後,開始配對。配對方法:男女兩人的期望和要等於兩人之間的好感度(條件:cx+cy==w[x][y])。每一輪匹配,無論是否成功,每個男生只會被嘗試匹配一次!

匹配過程:

第一輪匹配:

*************************===

女1:選擇了男3(此時女1--男3)

女2:也想選擇男3,男3已經在該輪匹配過了,女2無其他合適選擇,匹配失敗。

這一輪參與匹配的人有:女1,女2,男3。

怎麼辦???很容易想到的,這兩個女生只能降低一下期望值了,降低多少呢?兩個妹子都在能選擇的其他人中,也就是沒參與這輪匹配的男生中,選擇乙個期望值降低的盡可能小的人。(d=min也就是再其他人中選擇乙個最合適的。

比如:女1選擇男1,期望值要降低1。 女2選擇男1,期望值要降低1。 女2選擇男2,期望值要降低2。

於是,只要期望值降低1,就有妹子可能選擇其他人。所以妹子們的期望值要降低1點。

同時,剛才被搶的男生此時非常得意,因為有妹子來搶他,與是他的期望值提高了1點(就是同妹子們降低的期望值相同)。保持 cx+cy==w[x][y]

與是期望值變成這樣(當然,不參與剛才匹配過程的人期望值不變)

第二輪匹配:

*************************===

(女1已經在第一輪匹配完成了,女1--男3)

女2:選擇男1。(此時女1--男3,女2--男1)

女3:選擇男3,男3已經有女1了,於是女1嘗試換人,換到男1,男1已經被在這一輪被嘗試匹配過了。於是女1換人失敗,這一輪匹配失敗。

*************************===

再一次改變期望值。

這次三個女生都參與了匹配,男1和男3參與匹配。女生嘗試換人,於是期望值降低1。參與匹配的男生期望值增加1。

第三輪匹配:

*************************===

上一輪女1和女2是匹配完成的。(此時女1--男3,女2--男1)

女3:選擇男3,男3的當前物件女1嘗試換人,換到了男1,但是男1已經有女2了,於是女2再嘗試換人,換到了男2,於是女2--男2,女1--男1,女3--男3

匹配成功!!!撒花~~

*************************===

雖然不停換人的過程聽起來很麻煩,但其實整個是個遞迴的過程,實現起來比較簡單。比較複雜的部分就是期望值的改變,但是可以在遞迴匹配的過程中順帶求出來。

模板(帶詳細注釋)(入門題:hdu2255)

#include #include #include using namespace std;

const int maxn = 305;

const int inf = 0x3f3f3f3f;

int love[maxn][maxn]; // 記錄每個妹子和每個男生的好感度 即原理中的w[i][j]

int ex_girl[maxn]; // 每個妹子的期望值即原理中的cx[i]

int ex_boy[maxn]; // 每個男生的期望值即原理中的cy[i]

bool vis_girl[maxn]; // 記錄每一輪匹配匹配過的女生

bool vis_boy[maxn]; // 記錄每一輪匹配匹配過的男生

int match[maxn]; // 記錄每個男生匹配到的妹子 如果沒有則為-1

int slack[maxn]; // 記錄每個漢子如果能被妹子傾心最少還需要多少期望值原理中的d=cx[i]+cy[j]-w[i][j]=下面定義的gap

int n;

bool dfs(int girl)

} else

}return false;

}int km()

}// 嘗試為每乙個女生解決歸宿問題

for (int i = 0; i < n; ++i) }}

// 匹配完成 求出所有配對的好感度的和

int res = 0;

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

res += love[ match[i] ][i];

return res;

}int main()

return 0;

}

至此,我們再回顧km演算法的步驟:

1.用鄰接矩陣(或其他方法也行啦)來儲存圖。

2.運用貪心演算法初始化標桿。

3.運用匈牙利演算法找到完備匹配。 

4.如果找不到,則通過修改標桿,增加一些邊。 

5.重複3,4的步驟,直到完全匹配時可結束。 

KM演算法模板

這是hdu2255 include include include include includeusing namespace std const int maxn 305 const int inf 0x3f3f3f3f int love maxn maxn 記錄每個妹子和每個男生的好感度 in...

KM演算法模板

km演算法是用來求完全二分圖最大完美匹配的演算法,其原理是不斷尋找增廣路 增廣路定理 相關性質 在最大二分圖匹配圖中,w x y lx x ly y include include include include include using namespace std const int maxn ...

模板 KM演算法

km 演算法計算帶權二分圖最優匹配 模板一 dfs 演算法,時間複雜度 o n 4 const int maxn 310 const ll inf 0x3f3f3f3f3f3f3f3f match i j表示右邊的第i個點匹配左邊的第j個點,也可能這兩個點之間其實沒有連邊,也就是權值為零 int n...