Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 20394 | Accepted: 9309 |
Description
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 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
Sample Input
3 3 3 1 10 2 1 2 2 2 1 3 3 1 2 6
Sample Output
7
题意:
养猪场有M个猪圈(猪圈里面的个数固定),有N个人去买
这些买家有这些某些猪圈的钥匙,然后买家一个个来到猪场,买一定数量的猪
养猪场的主人会提前知道这些信息,然后安排最合理的卖猪计划,使得卖出去的猪最多
题意的理解:
将所有买家的钥匙收集起来,打开所有的猪圈,可以重新分配这些被打开的猪圈,然后使得卖出去的猪最多
题解:
利用网络流求最大流的算法Ford Fulkerson
构造容量网络:
每一个顾客作为除源点,汇点之外的点
利用本题的样例进行解析:
第一个和第二个猪圈的第一个顾客是 V1,那么设置一条路径 源点——V1 权值为3+1(表示猪圈1 2 的猪在这里)
第二个顾客买1 3 两个猪圈的,猪圈一在路径 源点——V1中 猪圈3在路径 源点——V2
第三个顾客买猪圈 2的猪,猪圈二的猪存放在 源点——V1中
然后每一个顾客需要买相应数量的猪,则都有一条路径通往汇点,权值顾客要买的猪的数量
Ford Fulkerson算法的主要思路:
先进行标号,然后找到增广流,直到汇点不能被标号
用一个 q 数组代表队列数组,把可以标号的节点加进去
用pre数组进行记录路径,记录是从某节点扫描到本节点的
用minflow数组记录增广流
用flow数组记录整个网络流,注意这个数组还要记录反向流
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define MAXN 110
#define INF 0x3f3f3f3f
int s,v;
int a[MAXN][MAXN];
void Ford_Fulkerson()
{
int flow[MAXN][MAXN];
int pre[MAXN],minflow[MAXN];
memset(flow,0,sizeof(flow));
minflow[0]=INF;//源点的输出流能力最大
while(1)
{
pre[0]=-1;//标号数组
for(int i=1;i<MAXN;i++)
pre[i]=-2;
int q[MAXN],first=0,endn=1;
q[first]=0;
int temp;
while(endn>first&&pre[v]==-2)
{
int start=q[first++];
for(int i=0;i<=v;i++){
if(pre[i]==-2&&(temp=a[start][i]-flow[start][i])){
pre[i]=start;
q[endn++]=i;
minflow[i]=minflow[start]<temp?minflow[start]:temp;
}
}
}
if(pre[v]==-2)
break;
int i,j;
for(i=pre[v],j=v;i!=-1;j=i,i=pre[i]){
flow[i][j]=flow[i][j]+minflow[v];
flow[j][i]=-flow[i][j];
}
}
int ans=0;
for(int i=1;i<v;i++)
ans+=flow[i][v];
printf("%d\n",ans);
}
void init()
{
int M,N,temp,k;
int num[MAXN*10];
int last[MAXN*10];
while(scanf("%d%d",&M,&N)!=EOF)
{
s=0,v=N+1;
memset(last,0,sizeof(last));
for(int i=1;i<=M;i++)
scanf("%d",&num[i]);
for(int i=1;i<=N;i++){
scanf("%d",&temp);
for(int j=0;j<temp;j++){
scanf("%d",&k);
if(last[k]==0){
a[s][i]+=num[k];//注意变量别搞混了
//流向买家i的猪的个数有两部分组成
//一部分是第一次被打开的猪圈
//一部分是已经打开的猪圈
}
else
a[last[k]][i]=INF;
last[k]=i;
}
scanf("%d",&a[i][v]);
}
Ford_Fulkerson();
}
}
int main()
{
//freopen("in.txt","r",stdin);
init();
return 0;
}