二分图'最佳匹配' KM算法

讲得很清楚的博客  推荐! 点我👍

附上一模板题 // hdu 2255(求最大权和)

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int INF = 0x3f3f3f3f;
 5 const int MAXN = 300+5;
 6 
 7 int n;
 8 int w[MAXN][MAXN];// 权值数组
 9 int cx[MAXN], cy[MAXN];// "标杆" --核心
10 
11 int love[MAXN];
12 bool visx[MAXN], visy[MAXN];
13 
14 bool dfs(int u) {
15     visx[u] = true;
16     for(int v = 1; v <= n; ++v) {
17         if(!visy[v] && cx[u] + cy[v] == w[u][v]) {
18             visy[v] = true;
19             if(!love[v] || dfs(love[v])) {
20                 love[v] = u;
21                 return true;
22             }
23         }
24     }
25     return false;
26 }
27 
28 int KM() {
29     for(int i = 1; i <= n; ++i) love[i] = 0;
30     for(int i = 1; i <= n; ++i) {
31         while(1) {
32             for(int j = 1; j <= n; ++j) visx[j] = visy[j] = false;
33             if(dfs(i)) break;
34             int d = INF;
35             for(int j = 1; j <= n; ++j) {
36                 if(visx[j]) {
37                     for(int k = 1; k <= n; ++k) {
38                         if(!visy[k]) d = min(d, cx[j]+cy[k]-w[j][k]);
39                     }
40                 }
41             }
42             for(int i = 1; i <= n; ++i) {
43                 if(visx[i]) cx[i] -= d;
44                 if(visy[i]) cy[i] += d;
45             }
46         }
47     }
48     int ans = 0;
49     for(int i = 1; i <= n; ++i) {
50         ans += w[love[i]][i];
51     }
52     return ans;
53 }
54 
55 int main() {
56     while(scanf("%d", &n) == 1) {
57         for(int i = 1; i <= n; ++i) {
58             int d = 0;
59             for(int j = 1; j <= n; ++j) {
60                 scanf("%d", &w[i][j]);
61                 d = max(d, w[i][j]);
62             }
63             cx[i] = d;
64             cy[i] = 0;
65         }
66         printf("%d\n", KM());
67     }
68     return 0;
69 }

// hdu 3488 (最小权值和)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<set>
 4 using namespace std;
 5 const int INF = 0x3f3f3f3f;
 6 const int MAXN = 200+5;
 7 
 8 int n, m;
 9 int w[MAXN][MAXN];
10 int cx[MAXN], cy[MAXN];
11 
12 int love[MAXN];
13 bool visx[MAXN], visy[MAXN];
14 
15 bool dfs(int u) {
16     visx[u] = true;
17     for(int v = 1; v <= n; ++v) {
18         if(!visy[v] && cx[u] + cy[v] == w[u][v]) {
19             visy[v] = true;
20             if(!love[v] || dfs(love[v])) {
21                 love[v] = u;
22                 return true;
23             }
24         }
25     }
26     return false;
27 }
28 
29 int KM() {
30     for(int i = 1; i <= n; ++i) love[i] = 0;
31     for(int i = 1; i <= n; ++i) {
32         while(1) {
33             for(int j = 1; j <= n; ++j) visx[j] = visy[j] = false;
34             if(dfs(i)) break;
35             int b = INF;
36             for(int j = 1; j <= n; ++j) {
37                 if(visx[j]) {
38                     for(int k = 1; k <= n; ++k) {
39                         if(!visy[k]) b = min(b, cx[j] + cy[k] - w[j][k]);
40                     }
41                 }
42             }
43             for(int j = 1; j <= n; ++j) {
44                 if(visx[j]) cx[j] -= b;
45                 if(visy[j]) cy[j] += b;
46             }
47         }
48     }
49     int ans = 0;
50     for(int i = 1; i <= n; ++i) {
51         ans += w[love[i]][i];
52     }
53     return -ans;
54 }
55 
56 int main() {
57     int T;
58     scanf("%d", &T);
59     while(T--) {
60         scanf("%d%d", &n, &m);
61         for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) w[i][j] = -INF;
62         int x, y, v;
63         set<int> xx[MAXN];
64         for(int i = 0; i != m; ++i) {
65             scanf("%d%d%d", &x, &y, &v);
66             if(-v > w[x][y]) w[x][y] = -v, xx[x].insert(v);
67         }
68         for(int i = 1; i <= n; ++i) {
69             cx[i] = -*xx[i].begin();
70             cy[i] = 0;
71         }
72         printf("%d\n", KM());
73     }
74     return 0;
75 }
View Code

 

posted @ 2019-11-05 23:20  pupil337  阅读(271)  评论(0编辑  收藏  举报