Hdu 4292 Food.cpp 最大流+拆点

题意:

给出 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 }

 

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292

posted @ 2012-09-18 20:18  Griselda.  阅读(351)  评论(0编辑  收藏  举报