您的位置:首页 > 其它

POJ 1149 PIGS (最大流)

2016-06-25 17:34 363 查看
PIGS

Time Limit: 1000MSMemory Limit: 10000K
Total Submissions: 19711Accepted: 9035
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

分析
主要是建图,增加一个源点和汇点,将源点和第一个有这个猪圈钥匙的顾客连起来,边权就是这个猪圈猪的数量,如果源点和某个节点有重边的话,合并就是了
之后的顾客对于已经开了的猪圈,将上一个顾客和他相连,边权是正无穷,可以用一个last数组来记录上一个买这个猪圈的顾客
每个顾客和汇点相连,边权是他想买猪的数量。


#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
//****************************************************
//最大流模板Edmonds_Karp算法
//初始化:G[][],st,ed
//******************************************************
const int MAXN = 200+10;
const int INF = 0x3fffffff;
int G[MAXN][MAXN];//存边的容量,没有边的初始化为0
int path[MAXN],flow[MAXN],st,ed;
int n;//点的个数,编号0~n,n包括了源点和汇点

queue<int>q;
int bfs()
{
int i,t;
while(!q.empty()) q.pop();//清空队列
memset(path,-1,sizeof(path));//每次搜索前都把路径初始化成-1
path[st]=0;
flow[st]=INF;//源点可以有无穷的流流进
q.push(st);
while(!q.empty()){
t=q.front();
q.pop();
if(t==ed) break;
for(i=0;i<=n;i++){
if(i!=st&&path[i]==-1&&G[t][i]){
flow[i]=flow[t]<G[t][i]?flow[t]:G[t][i];
q.push(i);
path[i]=t;
}
}
}
if(path[ed]==-1) return -1;//即找不到汇点上去了。找不到增广路径了
return flow[ed];
}

int Edmonds_Karp()
{
int max_flow=0;
int step,now,pre;
while((step=bfs())!=-1){
max_flow+=step;
now=ed;
while(now!=st){
pre=path[now];
G[pre][now]-=step;
G[now][pre]+=step;
now=pre;
}
}
return max_flow;
}

int val[1100];
int last[1100];

int main()
{
int N,M;
scanf("%d%d",&M,&N);
st=0,ed=N+1,n=N+1;
memset(val,0,sizeof(val));
memset(last,0,sizeof(last));
for(int i=1;i<=M;i++) scanf("%d",&val[i]);
for(int i=1;i<=N;i++){
int A,B,v;
scanf("%d",&A);
for(int j=1;j<=A;j++){
scanf("%d",&v);
if(last[v]==0){
G[st][i]+=val[v];
last[v]=i;
}
else{
G[last[v]][i]=INF;
last[v]=i;
}
}
scanf("%d",&B);
G[i][ed]=B;
}
printf("%d\n",Edmonds_Karp());

return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: