码迷,mamicode.com
首页 > 其他好文 > 详细

二分图匹配问题

时间:2018-08-13 19:35:21      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:++   name   二分图   ace   one   namespace   二分图匹配   clu   turn   

二分图最大匹配

 

二分图最大权匹配

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int LEN = 1e3 + 5;
 4 typedef long long ll;
 5 int n, n1, n2, m;
 6 const int oo = 1e9;
 7 ll ans;
 8 namespace KM {
 9     int qh, qt;
10     int w[LEN][LEN], q[LEN];
11     int lx[LEN], ly[LEN], pre[LEN], slk[LEN], nxt[LEN], vx[LEN], mat[LEN], vy[LEN];
12     void match(int &u) {
13         while (u) {
14             nxt[u] = pre[u];
15             swap(u, mat[pre[u]]);
16         }
17     }
18     void bfs(int s) {
19         qh = qt = 0;
20         vx[q[++qt] = s] = 1;
21         while (1) {
22             while (qh < qt) {
23                 int u = q[++qh];
24                 for (int v = 1; v <= n; v++) {
25                     int tmp;
26                     if (vy[v] || (tmp = lx[u] + ly[v] - w[u][v]) > slk[v]) continue;
27                     pre[v] = u;
28                     if (!tmp) {
29                         if (!nxt[v]) return match(v);
30                         vy[v] = vx[q[++qt] = nxt[v]] = 1;
31                     } else slk[v] = tmp;
32                 }
33             }
34             int a = oo;
35             for (int i = 1; i <= n; i++) {
36                 if (!vy[i] && a > slk[i]) a = slk[s = i];           
37             }
38             for (int i = 1; i <= n; i++) {
39                 if (vx[i]) lx[i] -= a;
40                 if (vy[i]) ly[i] += a;
41                 else slk[i] -= a;
42             }
43             if (!nxt[s]) return match(s);
44             vy[s] = vx[q[++qt] = nxt[s]] = 1;
45         }
46     }
47     void km() {
48         for (int i = 1; i <= n; i++) {
49             for (int j = 1; j <= n; j++) {
50                 slk[j] = oo;
51                 vx[j] = vy[j] = 0;
52                 lx[i] = max(lx[i], w[i][j]);
53             }
54             bfs(i);
55         }
56         ans = 0;
57         for (int i = 1; i <= n; i++) ans += lx[i] + ly[i];
58         printf("%lld\n", ans);
59         for (int i = 1; i < n1; i++) {
60             printf("%d ", w[i][mat[i]] ? mat[i] : 0);
61         }
62         printf("%d\n", w[n1][mat[n1]] ? mat[n1] : 0);
63     }
64 }
65 using namespace KM;
66 int main() {
67     scanf("%d %d %d", &n1, &n2, &m);
68     n = max(n1, n2);//左右的点的编号都是从1开始,n为较大的值
69     for (int i = 1; i <= m; i++) {
70         int x, y, z;//表示的是左边的第x个点和右边的第y个点可以花费z匹配
71         scanf("%d %d %d", &x, &y, &z);
72         w[x][y] = max(w[x][y], z);
73     }
74     km();
75     return 0;
76 }
KM

 

二分图匹配问题

标签:++   name   二分图   ace   one   namespace   二分图匹配   clu   turn   

原文地址:https://www.cnblogs.com/NineSwords/p/9470183.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!