网络流(最大流):POJ 1149 PIGS

PIGS

Time Limit: 1000ms
Memory Limit: 10000KB
This problem will be judged on PKU.
64-bit integer(整数) IO format: %lld      Java class name: Main
 
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 arives, 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.

Sample Input

3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6

Sample Output

7
  
  建模题,这里需要注意对空间的优化。
  题意:迈克有个养猪场,养猪场里有M个猪圈,每个猪圈都上了锁。迈克没有钥匙,而要买猪的顾客一个接一个来到养猪场,每个顾客有一些猪圈的钥匙,要买一定数量的猪。当每个顾客来时,将有钥匙的猪圈全部打开,从中挑出一些买走,然后迈克可以重新分配这些猪圈里面的猪。当顾客离开后,门又被锁上。问迈克最多可以卖多少猪。
  建模:先从源点给每个猪圈连一条边,容量是猪圈中猪的头数。这时再添加顾客,对于每一个顾客,查找他要开的每一个猪圈,如果他要开猪圈A,那么现在分情况讨论:
  <1>若以前(先后顺序,时间上的)没有顾客开过A猪圈,那么就连一条A到这个顾客的边,容量为INF,同时标记这个人为这个猪圈的“开启者”
  <2>若有,则将A的“开启者”连到这个人,容量为INF
  最后每个顾客连边到汇点,容量为各自的需求,接着跑一遍最大流就可以啦,这里我用了ISAP算法
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 
  6 using namespace std;
  7 const int INF=2147483647;
  8 const int maxn=1010,maxm=4010;
  9 int cnt,fir[maxn],nxt[maxm],cap[maxm],to[maxm],dis[maxn],gap[maxn],path[maxn],used[maxn];
 10 
 11 void addedge(int a,int b,int c)
 12 {
 13     nxt[++cnt]=fir[a];
 14     to[cnt]=b;
 15     cap[cnt]=c;
 16     fir[a]=cnt;
 17 }
 18 
 19 bool BFS(int S,int T)
 20 {
 21     memset(dis,0,sizeof(dis));
 22     dis[T]=1;
 23     queue<int>q;q.push(T);
 24     while(!q.empty())
 25     {
 26         int node=q.front();q.pop();
 27         for(int i=fir[node];i;i=nxt[i])
 28         {
 29             if(dis[to[i]])continue;
 30             dis[to[i]]=dis[node]+1;
 31             q.push(to[i]);
 32         }
 33     }
 34     return dis[S];
 35 }
 36 int fron[maxn];
 37 int ISAP(int S,int T)
 38 {
 39     if(!BFS(S,T))
 40         return 0;
 41     for(int i=1;i<=T;i++)++gap[dis[i]];
 42     int p=S,ret=0;
 43     memcpy(fron,fir,sizeof(fir));
 44     while(dis[S]<=T)
 45     {
 46         if(p==T){
 47             int f=INF;
 48             while(p!=S){
 49                 f=min(f,cap[path[p]]);
 50                 p=to[path[p]^1];
 51             }
 52             p=T;ret+=f;
 53             while(p!=S){
 54                 cap[path[p]]-=f;
 55                 cap[path[p]^1]+=f;
 56                 p=to[path[p]^1];
 57             }
 58         }
 59         int &ii=fron[p];
 60         for(;ii;ii=nxt[ii]){
 61             if(!cap[ii]||dis[to[ii]]+1!=dis[p])
 62                 continue;
 63             else 
 64                 break;
 65         }        
 66         if(ii){
 67             p=to[ii];
 68             path[p]=ii;
 69         }
 70         else{
 71             if(--gap[dis[p]]==0)break;
 72             int minn=T+1;
 73             for(int i=fir[p];i;i=nxt[i])
 74                 if(cap[i])
 75                     minn=min(minn,dis[to[i]]);
 76             gap[dis[p]=minn+1]++;
 77             fron[p]=fir[p];
 78             if(p!=S)
 79                 p=to[path[p]^1];        
 80         }
 81     }
 82     return ret;
 83 }
 84 
 85 void Init()
 86 {
 87     memset(fir,0,sizeof(fir));
 88     memset(used,0,sizeof(used)); 
 89     cnt=1;
 90 }
 91 int main()
 92 {
 93     int n,m,num,k,need;
 94     while(~scanf("%d%d",&m,&n))
 95     {
 96         Init();
 97         for(int i=1;i<=m;i++){
 98             scanf("%d",&num);
 99             addedge(0,i,num);
100             addedge(i,0,0);
101         }
102         for(int i=m+1;i<=m+n;i++){
103             scanf("%d",&k);
104             while(k--){
105                 scanf("%d",&num);
106                 if(used[num]){
107                     addedge(used[num],i,INF);
108                     addedge(i,used[num],0);
109                 }
110                 else{
111                     used[num]=i;
112                     addedge(num,i,INF);
113                     addedge(i,num,0);
114                 }
115                 
116             }
117             scanf("%d",&need);
118             addedge(i,n+m+1,need);
119             addedge(n+m+1,i,0);
120         }
121         printf("%d\n",ISAP(0,n+m+1));
122     }
123     return 0;
124 }

 

posted @ 2016-02-27 11:42  TenderRun  阅读(222)  评论(0编辑  收藏  举报