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 Source |
题意:略,注意两点:1.顾客是一个接一个来, 2.来了买了猪以后就马上锁上了猪房。
思路:网络流,重在构图。将每个顾客当做一个节点来表示,再加入超级源点和超级汇点。
1. 对于每个猪圈的第一个顾客,从源点向他连一条边,容量为猪圈里的猪的数量。
2. 对于每个猪圈,如果不是第一个顾客,则上一个打开这个猪圈的顾客向这个顾客连一条边,容量为 +∞。
3. 每个顾客到汇点连一条边,容量为各个顾客能买的数量。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int VM=1010; const int INF=0x3f3f3f3f; int m,n,src,des; int g[VM][VM],dep[VM],pig[VM],house[VM]; int BFS(){ queue<int> q; while(!q.empty()) q.pop(); memset(dep,-1,sizeof(dep)); dep[src]=0; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); for(int v=src;v<=des;v++) if(g[u][v]>0 && dep[v]==-1){ dep[v]=dep[u]+1; q.push(v); } } return dep[des]!=-1; } int DFS(int u,int minx){ if(u==des) return minx; int tmp; for(int v=src;v<=des;v++) if(g[u][v]>0 && dep[v]==dep[u]+1 && (tmp=DFS(v,min(minx,g[u][v])))){ g[u][v]-=tmp; g[v][u]+=tmp; return tmp; } return 0; } int Dinic(){ int ans=0,tmp; while(BFS()){ while(1){ tmp=DFS(src,INF); if(tmp==0) break; ans+=tmp; } } return ans; } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&m,&n)){ memset(house,0,sizeof(house)); memset(g,0,sizeof(g)); src=0, des=n+1; for(int i=1;i<=m;i++) scanf("%d",&pig[i]); int num,k; for(int i=1;i<=n;i++){ scanf("%d",&num); while(num--){ scanf("%d",&k); if(!house[k]) // 第k猪圈的第一个顾客,从源点向他连一条边 g[src][i]+=pig[k]; else g[house[k]][i]=INF; // 不是第一个顾客,上一个开这个猪圈的顾客向他连一条边。 house[k]=i; // 维护come[k] } scanf("%d",&g[i][des]); // 每个客户连到汇点的边 } printf("%d\n",Dinic()); } return 0; }
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 6 using namespace std; 7 8 const int maxn=1010; 9 const int INF=0x3f3f3f3f; 10 11 int map[110][110]; 12 int pre[110],vis[110]; 13 int pig[maxn],come[maxn]; 14 int n,m,ans,s,t; // 源点为s,汇点为t。 15 16 int BFS(){ 17 queue<int> q; 18 while(!q.empty()) 19 q.pop(); 20 memset(pre,-1,sizeof(pre)); 21 memset(vis,0,sizeof(vis)); 22 q.push(s); // 加入源点。 23 pre[s]=0; 24 vis[s]=1; 25 int cur; 26 while(!q.empty()){ 27 cur=q.front(); 28 q.pop(); 29 for(int i=s;i<=t;i++) 30 if(!vis[i] && map[cur][i]){ 31 vis[i]=1; 32 q.push(i); 33 pre[i]=cur; 34 if(i==t) // 到达汇点。 35 return 1; 36 } 37 } 38 return 0; 39 } 40 41 void EK(){ 42 int tmp; 43 while(BFS()){ 44 tmp=INF; 45 for(int i=t;i!=s;i=pre[i]) // 从汇点t开始,利用pre[]回溯,直到找到源点s。 46 tmp=min(tmp,map[pre[i]][i]); 47 for(int i=t;i!=s;i=pre[i]){ 48 map[pre[i]][i]-=tmp; 49 map[i][pre[i]]+=tmp; 50 } 51 ans+=tmp; 52 } 53 } 54 55 int main(){ 56 57 //freopen("input.txt","r",stdin); 58 59 while(~scanf("%d%d",&m,&n)){ 60 s=0,t=n+1; 61 memset(come,0,sizeof(come)); 62 memset(map,0,sizeof(map)); 63 for(int i=1;i<=m;i++) 64 scanf("%d",&pig[i]); 65 int num,k; 66 for(int i=1;i<=n;i++){ 67 scanf("%d",&num); 68 while(num--){ 69 scanf("%d",&k); 70 if(!come[k]) // 第k猪圈的第一个顾客,从源点向他连一条边 71 map[s][i]+=pig[k]; 72 else // 不是第一个顾客,上一个开这个猪圈的顾客向他连一条边。 73 map[come[k]][i]=INF; 74 come[k]=i; // 维护come[k] 75 } 76 cin>>map[i][t]; // 每个客户连到汇点的边 77 } 78 ans=0; 79 EK(); 80 printf("%d\n",ans); 81 } 82 return 0; 83 }