POJ 1149 PIGS(最大流)

Description

Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock any pighouse because he doesn't have the keys. Customers come to the farm one after another. Each of them has keys to some pig-houses and wants to buy a certain number of pigs.  All data concerning customers planning to visit the farm on that particular day are available to Mirko early in the morning so that he can make a sales-plan in order to maximize the number of pigs sold.  More precisely, the procedure is as following: the customer arrives, opens all pig-houses to which he has the key, Mirko sells a certain number of pigs from all the unlocked pig-houses to him, and, if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses.  An unlimited number of pigs can be placed in every pig-house.  Write a program that will find the maximum number of pigs that he can sell on that day.

Input

The first line of input contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100, number of pighouses and number of customers. Pig houses are numbered from 1 to M and customers are numbered from 1 to N.  The next line contains M integeres, for each pig-house initial number of pigs. The number of pigs in each pig-house is greater or equal to 0 and less or equal to 1000.  The next N lines contains records about the customers in the following form ( record about the i-th customer is written in the (i+2)-th line):  A K1 K2 ... KA B It means that this customer has key to the pig-houses marked with the numbers K1, K2, ..., KA (sorted nondecreasingly ) and that he wants to buy B pigs. Numbers A and B can be equal to 0.

Output

The first and only line of the output should contain the number of sold pigs.

 

题目大意:有n个人m个猪圈,每个猪圈里有一些猪,这n个人要买猪,每一个人会打开数个猪圈,买一些猪,然后这些猪圈的猪可以移动到另一些猪圈,问最多能卖多少猪。

思路:最大流。最朴素的想法是每个人建m个猪圈,不过这样搞点太多了。可以看到,若当两个猪圈被同时打开过,那么这此时两个猪圈就可以看成一个猪圈了。于是,对每一个猪圈,从源点到第一个打开它的人连一条边,容量为猪数,然后这个人再往下一个打开这个猪圈的人连一条边,容量为无穷大(其实这样两个人之间可能会有多条无穷大的边,不过我懒得搞,随便啦AC就好)。然后再从每个人连一条边到汇点,容量为这个人要买的猪的数量。最大流为答案。

PS:之前读入n、m的顺序搞错了WA了一次。n和m一样的样例太可恶了>_<

 

代码(16MS):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <queue>
  6 using namespace std;
  7 
  8 const int MAXN = 110;
  9 const int MAXE = MAXN * MAXN;
 10 const int INF = 0x7fffffff;
 11 
 12 struct SAP {
 13     int head[MAXN], gap[MAXN], pre[MAXN], dis[MAXN], cur[MAXN];
 14     int next[MAXE], to[MAXE], flow[MAXE];
 15     int ecnt, n, st, ed;
 16 
 17     void init() {
 18         memset(head, 0, sizeof(head));
 19         ecnt = 2;
 20     }
 21 
 22     void add_edge(int u, int v, int c) {
 23         to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
 24         to[ecnt] = u; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
 25     }
 26 
 27     void bfs() {
 28         queue<int> que; que.push(ed);
 29         memset(dis, 0x3f, sizeof(dis));
 30         dis[ed] = 0;
 31         while(!que.empty()) {
 32             int u = que.front(); que.pop();
 33             ++gap[dis[u]];
 34             for(int p = head[u]; p; p = next[p]) {
 35                 int &v = to[p];
 36                 if(flow[p ^ 1] && dis[v] > n) {
 37                     dis[v] = dis[u] + 1;
 38                     que.push(v);
 39                 }
 40             }
 41         }
 42     }
 43 
 44     int Max_flow(int ss, int tt, int nn) {
 45         st = ss, ed = tt, n = nn;
 46         int ans = 0, minFlow = INF, u;
 47         for(int i = 0; i <= n; ++i) {
 48             cur[i] = head[i];
 49             gap[i] = 0;
 50         }
 51         bfs();
 52         u = pre[st] = st;
 53         while(dis[st] < n) {
 54             bool flag = false;
 55             for(int &p = cur[u]; p; p = next[p]) {
 56                 int &v = to[p];
 57                 if(flow[p] && dis[u] == dis[v] + 1) {
 58                     flag = true;
 59                     minFlow = min(minFlow, flow[p]);
 60                     pre[v] = u;
 61                     u = v;
 62                     if(u == ed) {
 63                         ans += minFlow;
 64                         while(u != st) {
 65                             u = pre[u];
 66                             flow[cur[u]] -= minFlow;
 67                             flow[cur[u] ^ 1] += minFlow;
 68                         }
 69                         minFlow = INF;
 70                     }
 71                     break;
 72                 }
 73             }
 74             if(flag) continue;
 75             int minDis = n - 1;
 76             for(int p = head[u]; p; p = next[p]) {
 77                 int &v = to[p];
 78                 if(flow[p] && dis[v] < minDis) {
 79                     minDis = dis[v];
 80                     cur[u] = p;
 81                 }
 82             }
 83             if(--gap[dis[u]] == 0) break;
 84             ++gap[dis[u] = minDis + 1];
 85             u = pre[u];
 86         }
 87         return ans;
 88     }
 89 } G;
 90 
 91 int n, m;
 92 int last[1010];
 93 int a[1010], b[110];
 94 
 95 int main() {
 96     scanf("%d%d", &m, &n);
 97     G.init();
 98     int ss = n + 1, tt = n + 2;
 99     for(int i = 1; i <= m; ++i) scanf("%d", &a[i]);
100     for(int i = 1; i <= n; ++i) {
101         int x, b;
102         scanf("%d", &b);
103         for(int j = 1; j <= b; ++j) {
104             scanf("%d", &x);
105             if(last[x] == 0) G.add_edge(ss, i, a[x]);
106             else G.add_edge(last[x], i, INF);
107             last[x] = i;
108         }
109         scanf("%d", &x); G.add_edge(i, tt, x);
110     }
111     printf("%d\n", G.Max_flow(ss, tt, tt));
112 }
View Code

 

posted @ 2013-09-04 14:18  Oyking  阅读(276)  评论(0编辑  收藏  举报