题意:
给出 n 个人喜欢吃的食物和喜欢喝的饮料以及每种食物和饮料的数量
如果这个人可以吃到喜欢的食物则会感到高兴
问最多可以使多少人高兴
给出 n f d 表示现在有 n 个人 f 种食物还有d种饮料
接下去一行有 f 个数表示第 i 种食物的数量
接下去一行有 d 个数表示第 i 种饮料的数量
然后n行有f个数 Y表示喜欢第 i 种食物 N表示不喜欢
然后n行有d个数 Y N 意思一样
求出最多高兴的人数
思路:
建图求最大流..
就是把食物当成超级源点 饮料当成超级汇点
然后超级源点与每个人之间有连线 容量为食物的数量
超级汇点和每个人之间也有连线 容量为饮料的数量
然后根据每个人喜欢哪种食物或者是哪种饮料来连线
因为一个人只能选一种饮料和一种食物 所以拆点..然后容量为 1
Tips:
当用顶点容量限制的时候就使用拆点..
即确保这个点只会被用一次..
在这道题..拆点就把食物和饮料的限制连在一起了..
Code:
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <climits> 4 #define clr(x) memset(x, 0xff, sizeof(x)) 5 #define min(a,b)(a)<(b)?(a):(b) 6 7 const int INF = 0x1f1f1f1f; 8 const int maxn = 100010; 9 const int maxm = 200010; 10 struct Edge 11 { 12 int from; 13 int to; 14 int next; 15 int w; 16 }edge[maxm]; 17 int tot; 18 int head[maxn]; 19 20 void add(int s, int u, int f1, int f2) 21 { 22 edge[tot].from = s; 23 edge[tot].to = u; 24 edge[tot].w = f1; 25 edge[tot].next = head[s]; 26 head[s] = tot++; 27 edge[tot].from = u; 28 edge[tot].to = s; 29 edge[tot].w = f2; 30 edge[tot].next = head[u]; 31 head[u] = tot++; 32 } 33 34 int q[maxn]; 35 int cnt[maxn]; 36 int d[maxn]; 37 int low[maxn]; 38 int cur[maxn]; 39 40 int maxflow(int s, int t, int n) 41 { 42 int *front = q, *rear = q; 43 for(int i = 1; i <= n; ++i) { 44 d[i] = n; 45 cnt[i] = 0; 46 } 47 cnt[n] = n-1; 48 cnt[0]++; 49 d[t] = 0; 50 *rear++ = t; 51 while(front < rear) { 52 int v = *front++; 53 for(int i = head[v]; i != -1; i = edge[i].next) { 54 if(d[edge[i].to] == n && edge[i^1].w > 0) { 55 d[edge[i].to] = d[v] + 1; 56 cnt[n]--; 57 cnt[d[edge[i].to]]++; 58 *rear++ = edge[i].to; 59 } 60 } 61 } 62 63 int flow = 0, u = s, top = 0; 64 low[0] = INF; 65 for(int i = 1; i <= n; ++i) { 66 cur[i] = head[i]; 67 } 68 while(d[s] < n) { 69 int &i = cur[u]; 70 for(; i != -1; i = edge[i].next) { 71 if(edge[i].w > 0 && d[u] == d[edge[i].to]+1) { 72 low[top+1] = min(low[top], edge[i].w); 73 q[++top] = i; 74 u = edge[i].to; 75 break; 76 } 77 } 78 if(i != -1) { 79 if(u == t) { 80 int minf = low[top]; 81 for(int p = 1, i; p <= top; ++p) { 82 i = q[p]; 83 edge[i].w -= minf; 84 edge[i^1].w += minf; 85 } 86 flow += minf; 87 u = s; 88 low[0] = INF; 89 top = 0; 90 } 91 } 92 else { 93 int old_du = d[u]; 94 cnt[old_du]--; 95 d[u] = n-1; 96 for(int i = head[u]; i != -1; i = edge[i].next) 97 if(edge[i].w > 0 && d[u] > d[edge[i].to]) { 98 d[u] = d[edge[i].to]; 99 } 100 cnt[++d[u]]++; 101 if(d[u]<n) 102 cur[u] = head[u]; 103 if(u != s) { 104 u = edge[q[top]].from; 105 --top; 106 } 107 if(cnt[old_du] == 0) break; 108 } 109 } 110 return flow; 111 } 112 113 int main() 114 { 115 int i, j, k; 116 int n, f, d; 117 int fo, dr; 118 char cc; 119 while(scanf("%d %d %d", &n, &f, &d) != EOF) 120 { 121 clr(head); 122 tot = 0; 123 124 for(i = 2; i <= f+1; ++i) { 125 scanf("%d", &fo); 126 add(1, i, fo, 0); 127 } 128 int tt = f+d+2*n+2; 129 for(i = f+2*n+2; i < tt; ++i) { 130 scanf("%d", &dr); 131 add(i, tt, dr, 0); 132 } 133 134 for(i = f+2; i < n+f+2; ++i) { 135 getchar(); 136 for(j = 2; j <= f+1; ++j) { 137 scanf("%c", &cc); 138 if(cc == 'Y') add(j, i, 1, 0); 139 } 140 } 141 142 for(i = f+2; i < f+n+2; ++i) 143 add(i, i+n, 1, 0); 144 145 for(i = f+n+2; i < f+2*n+2; ++i) { 146 getchar(); 147 for(j = f+2*n+2; j < f+2*n+d+2; ++j) { 148 scanf("%c", &cc); 149 if(cc == 'Y') add(i, j, 1, 0); 150 } 151 } 152 153 int ans = maxflow(1, f+2*n+d+2, f+2*n+d+2); 154 printf("%d\n", ans); 155 } 156 return 0; 157 }