一共有n个人, m种收藏品, 每个人拥有的收藏品的种类和个数都是不相同的。 假设2-n这些人都只和1互相交换, 比例是1:1, 并且, 2-n这些人, 只换自己现在没有的, 如果他现在有第二种, 那么他就不会在去和别人换这一种。比如说第一个人有6个第一种, 2个第三种, 第二个人有2个第一种, 1个第二种, 那么第二个人就不会去和第一个人交换第二种, 而是去交换第三种。
问第一个人最后可以得到多少种不同的收藏品。
首先, 对于第一个人所拥有的收藏品, 建边(s, i+n, num[i]), 对于第2-n个人, 如果他所拥有的某种收藏品j的个数>1, 那么建边(i, j+n, num[j]-1), 如果没有某种收藏品, 那么建边(j+n, i, 1)。 对于所有收藏品, 建边(i+n, t, 1)。 最后跑一遍最大流即为答案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6 #define lson l, m, rt<<1 7 #define mem(a) memset(a, 0, sizeof(a)) 8 #define rson m+1, r, rt<<1|1 9 #define mem1(a) memset(a, -1, sizeof(a)) 10 #define mem2(a) memset(a, 0x3f, sizeof(a)) 11 #define rep(i, a, n) for(int i = a; i<n; i++) 12 #define ull unsigned long long 13 typedef pair<int, int> pll; 14 const double PI = acos(-1.0); 15 const double eps = 1e-8; 16 const int mod = 1e9+7; 17 const int inf = 1061109567; 18 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; 19 const int maxn = 2e5+5; 20 int cnt[55], num, q[maxn*4], head[maxn*2], dis[50], s, t; 21 struct node 22 { 23 int to, nextt, c; 24 node(){} 25 node(int to, int nextt, int c):to(to), nextt(nextt), c(c){} 26 }e[maxn*2]; 27 int bfs() { 28 mem(dis); 29 int st = 0, ed = 0; 30 dis[s] = 1; 31 q[ed++] = s; 32 while(st<ed) { 33 int u = q[st++]; 34 for(int i = head[u]; ~i; i = e[i].nextt) { 35 int v = e[i].to; 36 if(!dis[v]&&e[i].c) { 37 dis[v] = dis[u]+1; 38 if(v == t) 39 return 1; 40 q[ed++] = v; 41 } 42 } 43 } 44 return 0; 45 } 46 int dfs(int u, int limit) { 47 int cost = 0; 48 if(u == t) 49 return limit; 50 for(int i = head[u]; ~i; i = e[i].nextt) { 51 int v = e[i].to; 52 if(e[i].c&&dis[v] == dis[u]+1) { 53 int tmp = dfs(v, min(e[i].c, limit-cost)); 54 if(tmp>0) { 55 e[i].c -= tmp; 56 e[i^1].c += tmp; 57 cost += tmp; 58 if(cost == limit) 59 break; 60 } else { 61 dis[v] = -1; 62 } 63 } 64 } 65 return cost; 66 } 67 int dinic() { 68 int ans = 0; 69 while(bfs()) { 70 ans += dfs(s, inf); 71 } 72 return ans; 73 } 74 void add(int u, int v, int c) { 75 e[num] = node(v, head[u], c); head[u] = num++; 76 e[num] = node(u, head[v], 0); head[v] = num++; 77 } 78 void init() { 79 mem1(head); 80 num = 0; 81 } 82 int main() 83 { 84 int T, m, n, x, y; 85 cin>>T; 86 for(int casee = 1; casee <= T; casee++) { 87 cin>>n>>m; 88 init(); 89 s = 0, t = n+m+1; 90 for(int i = 1; i<=n; i++) { 91 scanf("%d", &x); 92 mem(cnt); 93 while(x--) { 94 scanf("%d", &y); 95 cnt[y]++; 96 } 97 if(i == 1) { 98 for(int j = 1; j<=m; j++) { 99 if(cnt[j]) 100 add(s, j+n, cnt[j]); 101 } 102 } else { 103 for(int j = 1; j<=m; j++) { 104 if(cnt[j]>1) { 105 add(i, j+n, cnt[j]-1); 106 } 107 if(cnt[j] == 0) { 108 add(j+n, i, 1); 109 } 110 } 111 } 112 } 113 for(int j = 1; j<=m; j++) { 114 add(j+n, t, 1); 115 } 116 printf("Case #%d: ", casee); 117 int ans = dinic(); 118 cout<<ans<<endl; 119 } 120 }