POJ1149 PIGS 【最大流 + 构图】

题目链接:http://poj.org/problem?id=1149

PIGS
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions:24094   Accepted: 10982

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.
题目大意:
1.给定m个猪棚,n个顾客,接下来n行每行代表第i个顾客有k个猪棚的钥匙,以及该顾客的需求量。
2.注意题目的要求,主人可以在顾客打开了猪棚的时候对猪棚中的猪数量进行调动,所以,为了尽可能满足所有顾客的需求,建图需要体现对猪的调动。
3.对于每一个猪棚,第一个打开它的顾客,我们将源点向该顾客建边,容量为猪棚的猪数量。对于以后再次光顾该猪棚的顾客,我们将第一次光顾该猪棚的顾客与以后光顾该猪棚的顾客建边,容量为inf。最后将每个顾客与终点连边,边的容量为顾客的需求量。至于为什么这样建图,可以理解为将猪全部给了第一个光顾该猪棚的顾客,以后再需要的顾客可以从他这里拿,这样的话可以确保尽可能多的满足后来的顾客。
代码如下:
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<queue>
  5 #define mem(a, b) memset(a, b, sizeof(a))
  6 using namespace std;
  7 const int MAXM = 1100; //猪圈数目上界 
  8 const int MAXN = 110; //顾客数目上界 
  9 const int inf = 0x3f3f3f3f;
 10 
 11 int m, n; //猪棚数目 顾客数目 
 12 int num[MAXM], first[MAXM], vis[MAXM];//每个猪圈里猪的数目 每个猪圈第一个顾客 每个猪圈是否已经有第一个顾客买了 
 13 int head[MAXN], cnt;
 14 int dep[MAXN];
 15 queue<int> Q;
 16 
 17 struct Edge
 18 {
 19     int to, next, flow;
 20 }edge[4 * MAXN + 2 * MAXN * MAXN];
 21 
 22 void add(int a, int b, int c)
 23 {
 24     cnt ++;
 25     edge[cnt].to = b;
 26     edge[cnt].flow = c;
 27     edge[cnt].next = head[a];
 28     head[a] = cnt;
 29 }
 30 
 31 int bfs(int st, int ed)
 32 {
 33     if(st == ed)
 34         return 0;
 35     while(!Q.empty())    Q.pop();
 36     mem(dep, -1);
 37     dep[st] = 1;
 38     Q.push(st);
 39     while(!Q.empty())
 40     {
 41         int index = Q.front();
 42         Q.pop();
 43         for(int i = head[index]; i != -1; i = edge[i].next)
 44         {
 45             int to = edge[i].to;
 46             if(edge[i].flow > 0 && dep[to] == -1)
 47             {
 48                 dep[to] = dep[index] + 1;
 49                 Q.push(to);
 50             }
 51         }
 52     }
 53     return dep[ed] != -1;
 54 }
 55 
 56 int dfs(int now, int ed, int zx)
 57 {
 58     if(now == ed)
 59         return zx;
 60     for(int i = head[now]; i != -1; i = edge[i].next)
 61     {
 62         int to = edge[i].to;
 63         if(dep[to] == dep[now] + 1 && edge[i].flow > 0)
 64         {
 65             int flow = dfs(to, ed, min(zx, edge[i].flow));
 66             if(flow > 0)
 67             {
 68                 edge[i].flow -= flow;
 69                 edge[i ^ 1].flow += flow;
 70                 return flow;
 71             }
 72         }
 73     }
 74     return -1;
 75 }
 76 
 77 void dinic(int st, int ed)
 78 {
 79     int ans = 0;
 80     while(bfs(st, ed))
 81     {
 82         while(1)
 83         {
 84             int inc = dfs(st, ed, inf);
 85             if(inc == -1)
 86                 break;
 87             ans += inc;
 88         }
 89     }
 90     printf("%d\n", ans);
 91 }
 92 
 93 int main()
 94 {
 95     int m, n;
 96     scanf("%d%d", &m, &n);
 97     int st = 0, ed = n + 1;
 98     mem(head, -1), cnt = -1;
 99     mem(first, -1), mem(vis, 0);
100     for(int i = 1; i <= m; i ++)
101         scanf("%d", &num[i]);
102     for(int i = 1; i <= n; i ++)
103     {
104         int k;
105         scanf("%d", &k);
106         for(int j = 1; j <= k; j ++)
107         {
108             int x;
109             scanf("%d", &x);//猪圈编号 
110             if(!vis[x])
111             {
112                 first[x] = i;
113                 vis[x] = 1;
114                 add(st, i, num[x]);
115                 add(i, st, 0);
116             }
117             else
118             {
119                 add(first[x], i, inf);
120                 add(i, first[x], 0);
121             }
122         }
123         int x;
124         scanf("%d", &x);
125         add(i, ed, x);
126         add(ed, i, 0);
127     }
128     dinic(st, ed);
129     return 0;
130 }
POJ1149

 

posted @ 2019-09-07 15:38  缘未到  阅读(145)  评论(0编辑  收藏  举报