UVA1349(帶權二分圖最大匹配 --> KM演算法模板)

來源:互聯網
上載者:User

標籤:this   需要   set   tin   lse   break   max   class   bsp   

UVA1349

題意:給定一些有向帶權邊,求出把這些邊構造成一個個環,總權值最小

解法:

對於帶權的二分圖的匹配問題可以用通過KM演算法求解。

要求最大權匹配就是初始化g[i][j]為0,直接跑就可以;

要求最小權匹配就是初始化g[i][j]為-INF,加邊的時候邊權為負,最後輸出答案的相反數。

 

因為要求每個點恰好屬於一個圈,意味著每個點都有一個唯一的後繼。 反過來,只要每個點都有唯一的後繼,每個點一定屬於某個圈。

唯一的是我們想到了二分圖的概念,我們對於每個點,建立由u到v的二分圖, 之後問題就轉換成了二分圖上的最小權完美匹配問題

  1 #include<bits/stdc++.h>  2 #define REP(i, a, b) for(int i = (a); i < (b); i++)  3 #define MEM(a,x) memset(a,x,sizeof(a))   4 #define INF 0x3f3f3f3f   5 #define MAXN 100+10  6 using namespace std;  7   8 struct KM {  9     int n; 10     int g[MAXN][MAXN]; 11     int Lx[MAXN], Ly[MAXN]; 12     int slack[MAXN];//記錄距X匹配到Y點還需要多少權值 13     int match[MAXN];//記錄每個X點匹配到的Y集中的點 14     bool S[MAXN], T[MAXN]; 15  16     void init(int n) { 17         this->n = n; 18         for (int i = 0; i < n; i++)  19             for (int j = 0; j < n; j++)  20                 g[i][j] = -INF; 21         //注意這裡如果是求最大權值匹配和就賦值為0 22         //最小權值匹配和就是—INF 23     } 24  25     void add_Edge(int u, int v, int val) { 26         g[u][v] = max(g[u][v], val); 27     } 28  29     bool dfs(int i) { 30         S[i] = true; 31         for (int j = 0; j < n; j++) { 32             if (T[j]) continue; 33             int tmp = Lx[i] + Ly[j] - g[i][j]; 34             if (!tmp) { 35                 T[j] = true; 36                 if (match[j] == -1 || dfs(match[j])) { 37                     match[j] = i; 38                     return true; 39                 } 40             } 41             else slack[j] = min(slack[j], tmp); 42         } 43         return false; 44     } 45  46     void update() { 47         int a = INF; 48         for (int i = 0; i < n; i++) 49             if (!T[i]) a = min(a, slack[i]); 50         for (int i = 0; i < n; i++) { 51             if (S[i]) Lx[i] -= a; 52             if (T[i]) Ly[i] += a; 53         } 54     } 55  56     void km() { 57         for (int i = 0; i < n; i++) { 58             match[i] = -1; 59             Lx[i] = -INF; Ly[i] = 0; 60             for (int j = 0; j < n; j++) 61                 Lx[i] = max(Lx[i], g[i][j]); 62         } 63         for (int i = 0; i < n; i++) { 64             for (int j = 0; j < n; j++) slack[j] = INF; 65             while (1) { 66                 for (int j = 0; j < n; j++) S[j] = T[j] = false; 67                 if (dfs(i)) break; 68                 else update(); 69             } 70         } 71     } 72 }Men; 73  74 int main() { 75     int n; 76     while (scanf("%d", &n) == 1 && n) { 77         Men.init(n); 78         REP(u, 0, n) { 79             int v; 80             while (scanf("%d", &v) && v) { 81                 int w; scanf("%d", &w); 82                 v--; 83                 Men.add_Edge(u, v, -w); 84             } 85         } 86  87         Men.km(); 88         int ans = 0, flag = 1; 89         REP(i, 0, n) { 90             if (Men.g[Men.match[i]][i] == -INF) { 91                 //有未匹配到,就是不成功,因為題目要求的是完美匹配 92                 flag = 0; 93                 break; 94             } 95             ans += Men.g[Men.match[i]][i];//累加權值 96         } 97         if (!flag) printf("N\n"); 98         else printf("%d\n", -ans);//最後是輸出的是負數 99     }100     return 0;101 }

 

UVA1349(帶權二分圖最大匹配 --> 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.