【二分圖最大權完美匹配】【KM演算法模板】【轉】

來源:互聯網
上載者:User

標籤:問題   get   print   詳解   tin   printf   include   clu   模板   

【文章詳解出處】https://www.cnblogs.com/wenruo/p/5264235.html

KM演算法是用來求二分圖最大權完美匹配的。【也就算之前的匈牙利演算法求二分最大匹配的變種??】

這裡就貼一下模板代碼..2333...

  1 #include <iostream>  2 #include <cstring>  3 #include <cstdio>  4 #include <algorithm>  5 using namespace std;  6 const int MAXN = 305;  7 const int INF = 0x3f3f3f3f;  8   9 int love[MAXN][MAXN];   // 記錄每個妹子和每個男生的好感度 10 int ex_girl[MAXN];      // 每個妹子的期望值 11 int ex_boy[MAXN];       // 每個男生的期望值 12 bool vis_girl[MAXN];    // 記錄每一輪匹配匹配過的女生 13 bool vis_boy[MAXN];     // 記錄每一輪匹配匹配過的男生 14 int match[MAXN];        // 記錄每個男生匹配到的妹子 如果沒有則為-1 15 int slack[MAXN];        // 記錄每個漢子如果能被妹子傾心最少還需要多少期望值 16  17 int N; 18  19  20 bool dfs(int girl) 21 { 22     vis_girl[girl] = true; 23  24     for (int boy = 0; boy < N; ++boy) { 25  26         if (vis_boy[boy]) continue; // 每一輪匹配 每個男生只嘗試一次 27  28         int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy]; 29  30         if (gap == 0) {  // 如果符合要求 31             vis_boy[boy] = true; 32             if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一個沒有匹配的男生 或者該男生的妹子可以找到其他人 33                 match[boy] = girl; 34                 return true; 35             } 36         } else { 37             slack[boy] = min(slack[boy], gap);  // slack 可以理解為該男生要得到女生的傾心 還需多少期望值 取最小值 備胎的樣子【捂臉 38         } 39     } 40  41     return false; 42 } 43  44 int KM() 45 { 46     memset(match, -1, sizeof match);    // 初始每個男生都沒有匹配的女生 47     memset(ex_boy, 0, sizeof ex_boy);   // 初始每個男生的期望值為0 48  49     // 每個女生的初始期望值是與她相連的男生最大的好感度 50     for (int i = 0; i < N; ++i) { 51         ex_girl[i] = love[i][0]; 52         for (int j = 1; j < N; ++j) { 53             ex_girl[i] = max(ex_girl[i], love[i][j]); 54         } 55     } 56  57     // 嘗試為每一個女生解決歸宿問題 58     for (int i = 0; i < N; ++i) { 59  60         fill(slack, slack + N, INF);    // 因為要取最小值 初始化為無窮大 61  62         while (1) { 63             // 為每個女生解決歸宿問題的方法是 :如果找不到就降低期望值,直到找到為止 64  65             // 記錄每輪匹配中男生女生是否被嘗試匹配過 66             memset(vis_girl, false, sizeof vis_girl); 67             memset(vis_boy, false, sizeof vis_boy); 68  69             if (dfs(i)) break;  // 找到歸宿 退出 70  71             // 如果不能找到 就降低期望值 72             // 最小可降低的期望值 73             int d = INF; 74             for (int j = 0; j < N; ++j) 75                 if (!vis_boy[j]) d = min(d, slack[j]); 76  77             for (int j = 0; j < N; ++j) { 78                 // 所有訪問過的女生降低期望值 79                 if (vis_girl[j]) ex_girl[j] -= d; 80  81                 // 所有訪問過的男生增加期望值 82                 if (vis_boy[j]) ex_boy[j] += d; 83                 // 沒有訪問過的boy 因為girl們的期望值降低,距離得到女生傾心又進了一步! 84                 else slack[j] -= d;//其實我感覺這一步無所謂,反正之後的slack[boy] = min(slack[boy], gap);也會更新slack[j].. 85             } 86         } 87     } 88  89     // 匹配完成 求出所有配對的好感度的和 90     int res = 0; 91     for (int i = 0; i < N; ++i) 92         res += love[ match[i] ][i]; 93  94     return res; 95 } 96  97 int main() 98 { 99     while (~scanf("%d", &N)) {100 101         for (int i = 0; i < N; ++i)102             for (int j = 0; j < N; ++j)103                 scanf("%d", &love[i][j]);104 105         printf("%d\n", KM());106     }107     return 0;108 }

 

【二分圖最大權完美匹配】【KM演算法模板】【轉】

相關關鍵詞:
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.