AC的故事大结局山寨版(下)
TimeLimit:2000MS MemoryLimit:128MB
64-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
每组输出一个整数,代表能带上武器驾车出击的警察最多有多少个
SampleInput
1 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 3
SampleOutput
3 这题的话有坑点,刚开始写的时候,是直接如下建图的
这样建图就会出现一种情况,一个人会被重复使用,
所以这时候就应该这一个点分成两个点,用流量为1的边连接,如果这个人使用了,流量减为0,这样就不会被重复使用
然后其他的就是标准的最小费用最大流解法了,用一个源点连接所有起始点,用一个汇点连接所有结束点,流量cap=1,cost=0,
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<queue> 5 using namespace std; 6 struct Dinic 7 { 8 static const int MAXN = 1025 + 7; ///改网络流的点 9 static const int MAXM = MAXN * MAXN; ///改网络流的边 10 static const int INF = 0x3f3f3f3f; ///看情况改 11 12 int n, m, s, t; 13 int first[MAXN], cur[MAXN], dist[MAXN], sign; 14 15 struct Node 16 { 17 int to, flow, next; 18 } edge[MAXM * 4]; 19 20 inline void init(int start, int vertex, int ss, int tt) 21 { 22 n = vertex, s = ss, t = tt; 23 for(int i = start; i <= n; i++ ) 24 { 25 first[i] = -1; 26 } 27 sign = 0; 28 } 29 inline void add_edge(int u, int v, int flow) 30 { 31 edge[sign].to = v, edge[sign].flow = flow, edge[sign].next = first[u]; 32 first[u] = sign++; 33 edge[sign].to = u, edge[sign].flow = 0, edge[sign].next = first[v]; 34 first[v] = sign++; 35 } 36 37 inline int dinic() 38 { 39 int max_flow = 0; 40 while(bfs(s, t)) 41 { 42 for(int i = 0; i <= n; i++ ) 43 { 44 cur[i] = first[i]; 45 } 46 max_flow += dfs(s, INF); 47 } 48 return max_flow; 49 } 50 bool bfs(int s, int t) 51 { 52 memset(dist, -1, sizeof(dist)); 53 queue<int>que; 54 que.push(s), dist[s] = 0; 55 while(!que.empty()) 56 { 57 int now = que.front(); 58 que.pop(); 59 if(now == t) 60 { 61 return 1; 62 } 63 for(int i = first[now]; ~i; i = edge[i].next) 64 { 65 int to = edge[i].to, flow = edge[i].flow; 66 if(dist[to] == -1 && flow > 0) 67 { 68 dist[to] = dist[now] + 1; 69 que.push(to); 70 } 71 } 72 } 73 return 0; 74 } 75 int dfs(int now, int max_flow) 76 { 77 if(now == t) 78 { 79 return max_flow; 80 } 81 int ans = 0, next_flow = 0; 82 for(int &i = cur[now]; ~i; i = edge[i].next) 83 { 84 int to = edge[i].to, flow = edge[i].flow; 85 if(dist[to] == dist[now] + 1 && flow > 0) 86 { 87 next_flow = dfs(to, min(max_flow - ans, flow)); 88 ans += next_flow; 89 edge[i].flow -= next_flow; 90 edge[i ^ 1].flow += next_flow; 91 if(ans == max_flow) 92 { 93 return max_flow; 94 } 95 } 96 } 97 if(ans == 0) 98 { 99 return dist[now] = 0; 100 } 101 return ans; 102 } 103 104 } dinic; 105 106 /** 107 .init(点编号起点, 点编号终点, 源点, 汇点) 108 .add_edge(u, v, w) 加边 109 .dinic() 输出最大流 110 */ 111 112 int a[1200],b[2000]; 113 int main() 114 { 115 int t,p,f,c; 116 scanf("%d",&t); 117 while(t--) 118 { 119 int s=0,t=1000; 120 dinic.init(s,t,s,t); 121 122 scanf("%d%d%d",&p,&f,&c); 123 for(int i=1; i<=f; i++) ///s->车 124 dinic.add_edge(s,i,1); 125 for(int i=1;i<=p;i++) 126 dinic.add_edge(i+200,i+400,1); 127 for(int i=1; i<=c; i++) 128 dinic.add_edge(i+600,t,1); ///枪->t 129 for(int i=1; i<=p; i++) 130 { 131 int x,y; 132 scanf("%d%d",&x,&y); 133 for(int j=1; j<=x; j++) ///车 134 { 135 int z; 136 scanf("%d",&z); 137 dinic.add_edge(z,i+200,1); 138 } 139 for(int j=1; j<=y; j++) 140 { 141 int z; 142 scanf("%d",&z); 143 dinic.add_edge(i+400,z+600,1); 144 } 145 } 146 printf("%d\n",dinic.dinic()); 147 } 148 return 0; 149 }
原文地址:https://www.cnblogs.com/yuanlinghao/p/9432982.html