AC的故事大结局山寨版(下)(最大流)
Posted Q1143316492
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC的故事大结局山寨版(下)(最大流)相关的知识,希望对你有一定的参考价值。
AC的故事大结局山寨版(下)
TimeLimit:2000MS MemoryLimit:128MB64-bit integer IO format:%lld已解决 | 点击收藏Problem Description小A算出幕后黑手的人员是如此之多,知道在我们华夏,手段通天者必然身居高位,仅仅靠他们的力量恐怕难以和他们对抗。
于是小A和小C找到了以前认识的检察官侯亮平,告诉侯亮平事情的始末后,他们立马通知赵东来安排了人手准备逮捕嫌疑人祁同伟(这么大的事居然没有事先向上级汇报就擅自行动)。
现在警厅里只有P<=100个警察,F<=100辆警车和C<=100把武器,每辆车和每把武器都有自己的特点,每个警察只会用其中的一些警车和武器。
每辆警车只坐一名警察(不知道为何要这么浪费资源,可能市局比较有钱),每位警察必须带上自己熟练的武器才能驾车出击。
为了打败幕后黑手祁同伟,小A合理安排后派出了最多的人手,相信你也一定知道派出了多少警察。最终成功逮捕了嫌疑人祁同伟。
从此小A和小C过上了幸福快乐的日子。可喜可贺,可喜可贺。
Input先输入一个整数t(<=100)表示有多少组数据
每组输入3个整数P,F,C,(3个数都不超过100)分别表示警察人数,警车数量和武器数量。
接着第i行表示第i个警察的能力(共P行)。该行先输入两个整数x,y表示该警察会驾驶x辆汽车和y把武器,之后有x个整数表示警车的编号和y个整数表示武器的编号。
(警车编号:1~F,武器编号:1~C)
Output每组输出一个整数,代表能带上武器驾车出击的警察最多有多少个
SampleInput1 4 3 3 2 2 1 2 3 1 2 2 2 3 1 2 2 2 1 3 1 2 2 1 1 3 3SampleOutput3
思路:警察,武器,车都看作点,虚拟出源点汇点。保证源点到汇点必须经过一个警察,一个武器,一辆车。另外,警察要拆成两个点,为了避免警察被使用多次。所有关系作为流为1的边
正确的图:
错误的图:
如果有一个人可以使用多个武器多辆车,那么该警察可能被使用多次。如下图,警察1就会贡献流量2。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int MAXN = 1001; 5 const int MAXM = 1e4 + 7; 6 const int INF = 0x7fffffff; 7 typedef long long LL; 8 9 int s, t, p, f, c; 10 11 struct Edge { 12 int to, w, next; 13 } edge[MAXM * 4]; 14 15 int first[MAXN], cur[MAXN], sign, dist[MAXN]; 16 17 inline void init() { 18 for(int i = 0; i < MAXN; i ++ ) { 19 first[i] = -1; 20 } 21 sign = 0; 22 } 23 24 inline void add_edge(int u,int v,int w) { 25 edge[sign].to = v, edge[sign].w = w; 26 edge[sign].next = first[u], first[u] = sign++; 27 edge[sign].to = u, edge[sign].w = 0; 28 edge[sign].next = first[v], first[v] = sign++; 29 } 30 31 bool bfs(int s,int t) { 32 memset(dist, -1, sizeof(dist)); 33 queue<int>que; 34 que.push(s), dist[s] = 0; 35 while(!que.empty()) { 36 int now = que.front(); 37 que.pop(); 38 if(now == t) { 39 return 1; 40 } 41 for(int i = first[now]; ~i; i = edge[i].next) { 42 int to = edge[i].to, ww = edge[i].w; 43 if(dist[to] == -1 && ww > 0) { 44 dist[to] = dist[now] + 1; 45 que.push(to); 46 } 47 } 48 } 49 return 0; 50 } 51 52 int dfs(int s, int t, int max_flow) { 53 if(s == t) { 54 return max_flow; 55 } 56 for(int &i = cur[s]; ~i; i = edge[i].next) { 57 int to = edge[i].to, ww = edge[i].w; 58 if(dist[to] == dist[s] + 1 && ww > 0) { 59 int flow = dfs(to, t, min(max_flow, ww)); 60 if(flow > 0) { 61 edge[i].w -= flow; 62 edge[i ^ 1].w += flow; 63 return flow; 64 } 65 } 66 } 67 return 0; 68 } 69 70 int dinic(int s, int t) { 71 int ans = 0; 72 while(bfs(s, t)) { 73 for(int i = 0; i < MAXN; i ++ ) { 74 cur[i] = first[i]; 75 } 76 ans += dfs(s, t, INF); 77 } 78 return ans; 79 } 80 81 template<class T> 82 inline bool nextInt(T &n) 83 { 84 T x = 0, tmp = 1; char c = getchar(); 85 while((c < \'0\' || c > \'9\') && c != \'-\' && c != EOF) c = getchar(); 86 if(c == EOF) return false; 87 if(c == \'-\') c = getchar(), tmp = -1; 88 while(c >= \'0\' && c <= \'9\') x *= 10, x += (c - \'0\'),c = getchar(); 89 n = x*tmp; 90 return true; 91 } 92 93 template<class T> 94 inline void out(T n) 95 { 96 if(n < 0) 97 { 98 putchar(\'-\'); 99 n = -n; 100 } 101 int len = 0,data[20]; 102 while(n) 103 { 104 data[len++] = n%10; 105 n /= 10; 106 } 107 if(!len) data[len++] = 0; 108 while(len--) putchar(data[len]+48); 109 } 110 111 int main() { 112 int T; 113 nextInt(T); 114 while(T--) { 115 nextInt(p), nextInt(f), nextInt(c); 116 s = 0, t = 1000; 117 init(); 118 for(int i = 1; i <= f; i++ ) { ///s->car 119 add_edge(s, i, 1); 120 } 121 for(int i = 1; i <= p; i++ ) { ///line 122 add_edge(i + 200, i + 400, 1); 123 } 124 for(int i = 1; i <= c; i++ ) { ///gun->t 125 add_edge(i + 600, t, 1); 126 } 127 for(int i = 1; i <= p; i++ ) { 128 int x, y, id; 129 nextInt(x), nextInt(y); 130 for(int j = 1; j <= x; j++ ) { ///car 131 nextInt(id); 132 add_edge(id, i + 200, 1); 133 } 134 for(int j = 1; j <= y; j++ ) { ///gun 135 nextInt(id); 136 add_edge(i + 400, id + 600, 1); 137 } 138 } 139 out(dinic(s, t)), putchar(\'\\n\'); 140 } 141 142 return 0; 143 }
以上是关于AC的故事大结局山寨版(下)(最大流)的主要内容,如果未能解决你的问题,请参考以下文章
解锁PK!全球首款屏下指纹手机对战iPhone X:结局很意外