UOJ#80. 二分图最大权匹配 模板

#80. 二分图最大权匹配

从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生。编号分别为 1,,nl1,…,nl 和 1,,nr1,…,nr。

有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为配偶,且结为配偶后幸福程度为 ww。

请问这个班级里幸福程度之和最大是多少?

输入格式

第一行三个正整数,nl,nr,mnl,nr,m。

接下来 mm 行,每行三个整数 v,u,wv,u,w 表示第 vv 个男生和第 uu 个女生愿意结为配偶,且幸福程度为 ww。保证 1vnl1≤v≤nl,1unr1≤u≤nr,保证同一对 v,uv,u 不会出现两次。

输出格式

第一行一个整数,表示幸福程度之和的最大值。

接下来一行 nlnl 个整数,描述一组最优方案。第 vv 个整数表示 vv 号男生的配偶的编号。如果 vv 号男生没配偶请输出 00。

样例一

input

2 2 3
1 1 100
1 2 1
2 1 1

output

100
1 0

限制与约定

1nl,nr4001≤nl,nr≤400,1m1600001≤m≤160000,1w1091≤w≤109。

时间限制1s1s

空间限制256MB256MB

下载

样例数据下载

 

 

http://blog.csdn.net/c20180630/article/details/71080521这篇讲的不错

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <vector>
 8 #include <map>
 9 #include <string> 
10 #include <cmath> 
11 #define min(a, b) ((a) < (b) ? (a) : (b))
12 #define max(a, b) ((a) > (b) ? (a) : (b))
13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
14 template<class T>
15 inline void swap(T &a, T &b)
16 {
17     T tmp = a;a = b;b = tmp;
18 }
19 inline void read(long long &x)
20 {
21     x = 0;char ch = getchar(), c = ch;
22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
24     if(c == '-') x = -x;
25 }
26 
27 const long long INF = 0x3f3f3f3f3f3f3f3f;
28 const long long MAXN = 4000 + 10;
29 
30 long long g[MAXN][MAXN], n1, n2, m, tmp1, tmp2, lab1[MAXN], lab2[MAXN], lk1[MAXN], lk2[MAXN], pre[MAXN], sla[MAXN], vis[MAXN];
31 void fac(long long x)
32 {
33     memset(vis, 0, sizeof(vis)), memset(pre, 0, sizeof(pre)), memset(sla, 0x7f, sizeof(sla)), vis[0] = 1;
34     long long y;
35     do
36     {
37         y = 0;
38         for(long long i = 1;i <= n2;++ i)
39         {
40             if(vis[i]) continue;
41             if(lab1[x] + lab2[i] - g[x][i] < sla[i]) sla[i] = lab1[x] + lab2[i] - g[x][i], pre[i] = x;
42             if(sla[i] < sla[y]) y = i;
43         }
44         long long d = sla[y];
45         for(long long i = 1;i <= n1;++ i) if(vis[lk1[i]]) lab1[i] -= d;
46         for(long long i = 1;i <= n2;++ i) if(vis[i]) lab2[i] += d; else sla[i] -= d;
47         vis[y] = 1; 
48     }while(x = lk2[y]);
49     for(;y;swap(y, lk1[lk2[y] = pre[y]]));
50 }
51 long long KM()
52 {
53     for(long long i = 1;i <= n1;++ i) fac(i);
54     long long ans = 0;
55     for(long long i = 1;i <= n1;++ i) ans += g[i][lk1[i]];
56     return ans;
57 }
58 int main()
59 {
60     read(n1), read(n2), n2 = max(n2, n1), read(m);
61     for(long long i = 1;i <= m;++ i)read(tmp1), read(tmp2), read(g[tmp1][tmp2]), lab1[tmp1] = max(g[tmp1][tmp2], lab1[tmp1]);
62     printf("%lld\n", KM());
63     for(long long i = 1;i <= n1;++ i) printf("%lld ", g[i][lk1[i]] ? lk1[i] : 0);
64     return 0;
65 }
UPJ#80

 

posted @ 2018-01-30 10:33  嘒彼小星  阅读(351)  评论(0编辑  收藏  举报