http://poj.org/problem?id=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.
Sample Input
3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6
Sample Output
7
题意:
输入第一行给你n个猪圈,m个顾客。
第二行n个数,分别表示第i个猪圈里有多少头猪。
然后后m行,每行第一个数表示第i个人有k把钥匙,后k个数为他的钥匙能开的猪圈标号。最后一个数表示他需要多少头猪。
所有开着门的猪圈里的猪能相互串。(人买走猪后就把猪圈锁上了)
求最多能卖多少头猪。
如何建图:
建立一个超级源点S,S向每一个客户连接一个容量为客户想买的猪圈内猪的总量的边,客户向想要买的猪圈连接一个极大值(所有的猪量),而且猪圈内部(这一轮的猪圈可以向下一轮流通,因为一轮结束之后可以互换)也要连边(但是最后体现出来的是客户之间在连边),最后所有客户向超级汇点连接一个自己购买量的边(限制)
然后怎样简化这个图,尤其是为什么在客户之间连边这个很巧妙,这样让猪能够自由流动
#include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<cstdio> #include<queue> #include<map> #include<vector> #include<set> using namespace std; const int maxn=1300; const int INF=0x3fffffff; typedef long long LL; typedef unsigned long long ull; //dinic int d[110]; int f[110][110]; int cow[maxn]; int pre[maxn]; int n,m; int bfs(int s){ int q[maxn]; q[0]=0; //模拟队列 //0是超级源点 memset(d,-1,sizeof(d)); //初始化层次 d[s]=0; int front=0,rear=1; while(front<rear){ int t=q[front++]; for(int j=0;j<=n+1;j++){ if(d[j]==-1&&f[t][j]>0){ //没访问过而且有连边 d[j]=d[t]+1; q[rear++]=j; } } } if(d[n+1]>=0) return 1; ///n+1是超级汇点 else return 0; } int dinic(int t,int sum){ if(t==n+1) return sum; int os=sum; for(int i=0;i<=n+1&∑i++){ //sum=0的时候可以自动退出 if(d[i]==d[t]+1&&f[t][i]>0){ //可行流 int a=dinic(i,min(sum,f[t][i])); f[t][i]-=a; f[i][t]+=a; sum-=a; } } return os-sum; } int main(){ scanf("%d %d",&m,&n); int tot=0; for(int i=1;i<=m;i++){ //这个是每个猪圈的初始猪数 scanf("%d",&cow[i]); tot+=cow[i]; } int num,x,y; for(int i=1;i<=n;i++){ scanf("%d",&num); for(int j=1;j<=num;j++){ scanf("%d",&x); if(pre[x]==0) f[0][i]+=cow[x]; // 当猪圈被第一次打开时,在源点与当前顾客之间连接一条边,容量为该猪圈的猪的头数 else f[pre[x]][i]=tot;//当某个猪圈 不是被第一次打开时,在上一个打开该猪圈的顾客与当前打开该猪圈的顾客之间连接一条边,容量为无穷大 pre[x]=i; } scanf("%d",&y); f[i][n+1]=y; //在每个顾客与汇点之间连接一条边,容量为该顾客要买猪的头数 } int res=0; while(bfs(0)){ res+=dinic(0,INF); } printf("%d",res); return 0; }