日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

二分图匹配问题

發(fā)布時間:2024/4/18 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二分图匹配问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最大匹配

N對人兩兩之間存在關(guān)系,求最多的匹配

  • 最小點覆蓋=最大匹配
  • 最大獨立集=頂點數(shù)-最大匹配
  • 最小路徑覆蓋=頂點數(shù)-最大匹配
    匈牙利算法:時間O(n3,nm{n^3}, {nm}n3nm),空間O(n2,n+m{n^2,n+m}n2n+m)
int g[maxn][maxn]; // 記錄兩個人的關(guān)系 int girl[maxn], used[maxn]; // girl記錄已經(jīng)確定的關(guān)系 // used 記錄每次增廣路上右邊的點 int find (int x) {for (int i = 1; i <= n; ++i) {// 對于X遍歷右邊的點,如果X與i存在關(guān)系而且i在本輪還沒有確定關(guān)系,那么X和i就有可能匹配,先標(biāo)記下if (g[x][i] && used[i] == 0) {used[i] = 1;// 如果i沒有被匹配 or i已經(jīng)被前面的點匹配過了而且之前的人還能找到其他人匹配,X就和i可以正式確定關(guān)系if (!girl[i] || find(girl[i])) {girl[i] = x;return true;}}}return false; } for (int i = 1; i <= n; ++i) {mem(used, 0);ans += find(i); }

最佳匹配

最佳匹配是完備匹配,每個人都要被匹配。在完備匹配的基礎(chǔ)上求一種權(quán)值最大的匹配

  • KM算法:設(shè)置兩個頂標(biāo)(左邊頂點賦值為對應(yīng)邊的最大權(quán)值,右邊賦值為0)先按照最大的權(quán)值選邊(匈牙利算法),選邊沖突時計算增廣路上最小的降低費用,更新每個點(增廣路上左邊的點減去費用,右邊的點加上費用)這樣保證增廣路可以繼續(xù)找到解而且之前連接的邊也存在,這樣遍歷每個點即可。
  • 如果求權(quán)值和最小的最佳匹配,存負(fù)邊即可。
  • 如果不是完全圖,計算的時候可以將沒有給出的邊賦值為**-inf**這樣不會影響答案,統(tǒng)計答案的時候判定一下即可。
int n; int usex[maxn], usey[maxn], topx[maxn], topy[maxn], slack[maxn]; int girl[maxn], g[maxn][maxn]; // usex, usey 用在每次的匈牙利算法記錄增廣路上的點,方便后面調(diào)整頂標(biāo)的權(quán)值 // girl 記錄已經(jīng)確定的關(guān)系 // topx, topy記錄左右的頂標(biāo) int dfs(int x) {usex[x] = 1; // 增光路左邊的點for (int i = 1; i <= n; ++i) {if (usey[i]) continue;int tmp = topx[x] + topy[i] - g[x][i]; if (tmp != 0) { // tmp = 0,邊有效slack[i] = min(tmp, slack[i]); // 記錄最小降低值}else {usey[i] = 1; // 增光路右邊的點if (girl[i] == -1 || dfs(girl[i])) {girl[i] = x;return 1;}}}return 0; } int km() {memset(girl, -1, sizeof(girl));memset(topx, 0, sizeof(topx));memset(topy, 0, sizeof(topy));// 更新topx為最大值for (int i = 1; i <= n; ++i) {for (int j = 1; j <= n; ++j) {topx[i] = max(topx[i], g[i][j]);}}for (int i = 1; i <= n; ++i) {memset(slack, inf, sizeof(slack));while (1) {memset(usex, 0, sizeof(usex));memset(usey, 0, sizeof(usey));if (dfs(i)) break;int tmp = inf;// 取最小的降低值for (int j = 1; j <= n; ++j) {if (usey[j]) continue;tmp = min(tmp, slack[j]);}if (tmp == inf) return -1;// 更新左頂標(biāo)for (int j = 1; j <= n; ++j) {if (usex[j]) topx[j] -= tmp;}// 更新右頂標(biāo)for (int j = 1; j <= n; ++j) {if (usey[j]) topy[j] += tmp;else slack[j] -= tmp;}}}int ans = 0;for (int i = 1; i <= n; ++i) {if (girl[i] != -1) ans += g[girl[i]][i];}return ans; }

總結(jié)

以上是生活随笔為你收集整理的二分图匹配问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。