Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13677 | Accepted: 6044 |
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
這題難點在於如何建圖,如何理解題目中的“if Mirko wants, he can redistribute the remaining pigs across the unlocked pig-houses.”也將成爲建圖的關鍵。
如果我們把每個顧客作爲圖中的點,則對於擁有某個豬圈的鑰匙的連續的兩個顧客i和j,建一條邊i->j。現在解釋爲何可以這樣建邊:比如說i擁有豬圈1,2,3的鑰匙,j擁有豬圈1的鑰匙,這樣i,j同時擁有3號豬圈的鑰匙,按理說j只能打開1號豬圈,但i顧客購買豬後,Mirko是可以隨意分配1,2,3中豬的數量的,所以j顧客實質上是可以得到1,2,3中的豬的。
因爲豬圈有m個,所以我們可以加一個源點s,分別與n個顧客建邊,鑑於上面的建邊方式,s應與每個豬圈的第一個顧客建邊,邊容量爲豬圈中豬的數量,若某個顧客同時爲多個豬圈的第一個顧客,則數量相加。
每個顧客購買豬的數量是有上限的,所以我們應該引入一個匯點t,每個顧客與t建一條邊,邊容量爲每個顧客需要購買的豬的數量。
#include <iostream>
#include<cstdio>
using namespace std;
const int MAXN=105;
const int INF=(1<<29);
int flow[MAXN][MAXN];//容量限制
int dalta[MAXN];//改變量
int pre[MAXN];
int flag[MAXN];//標號
int m,n;
int EK()
{
int i,maxflow=0;
int queue[MAXN],front,rear;
while(1)
{
front=rear=0;
for(i=1;i<=n+1;i++)
flag[i]=0;
flag[0]=1;
pre[0]=0;
dalta[0]=INF;
queue[rear++]=0;
while(front!=rear&&!flag[n+1])
{
int v=queue[front++];
for(i=1;i<=n+1;i++)
{
if(flag[i])
continue;
if(flow[v][i])
{
dalta[i]=min(dalta[v],flow[v][i]);
flag[i]=1;
pre[i]=v;
queue[rear++]=i;
}
}
}
if(!flag[n+1])
break;
maxflow+=dalta[n+1];
i=n+1;
while(i!=0)
{
flow[pre[i]][i]-=dalta[n+1];
flow[i][pre[i]]+=dalta[n+1];
i=pre[i];
}
}
return maxflow;
}
int main()
{
int i,j;
int pigs[1005];//每個豬圈中的豬的數量
int before[1005];//每個豬圈的前一個顧客
while(~scanf("%d%d",&m,&n))
{
for(i=0;i<=n+1;i++)
for(j=0;j<=n+1;j++)
flow[i][j]=0;
for(i=1;i<=m;i++)
{
scanf("%d",pigs+i);
before[i]=-1;
}
for(i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
while(num--)
{
scanf("%d",&j);
if(before[j]==-1)
{
before[j]=i;
flow[0][i]+=pigs[j];
}
else
{
flow[before[j]][i]=INF;
before[j]=i;
}
}
scanf("%d",&j);
flow[i][n+1]=j;
}
printf("%d\n",EK());
}
return 0;
}