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 ", G.Max_flow(ss, tt, tt)); 112 }