http://poj.org/problem?id=1149
/*
一开始没很懂题意 ,将 猪圈 和人 一起建了一个图 写了一个最大六模版,可是结果始终
和样例不一样,有读了一遍题 ,题中说 猪圈打开后可以重新调整猪的分配。
这才明白。
1. 对于每个猪圈的第一个顾客,从源点向他连一条边,容量为猪圈里的猪的数量。
2. 对于每个猪圈,如果不是第一个顾客,则上一个打开这个猪圈的顾客向这个顾客连一条边,容量为 +∞。(便于调整猪的重新分配)
3. 每个顾客到汇点连一条边,容量为各个顾客能买的数量。
*/
#include<stdio.h>
#include<string.h>
#define inf 0x7fffffff
#define maxn 20000
int min(int x,int y)
{
if(x<y)return x;
else return y;
}
int n,m,N;
int p[maxn],ans;
int map[1010][1010],vis[maxn],have[maxn],cost[maxn],pre[maxn];
int bfs()
{
memset(vis,0,sizeof(vis));
int i,head=0,tail=0;
p[head]=0;
tail++;
vis[0]=1;
while(head!=tail)
{
int k=p[head];
if(k==m)return 1;
for(i=0;i<=m;i++)
{
if(!vis[i]&&map[k][i])
{
vis[i]=1;
pre[i]=k;
p[tail++]=i;
if(i==m)return 1;
if(tail==maxn)tail=0;
}
}
head++;
if(head==maxn)head=0;
}
return 0;
}
void EK()
{
int i,sum=inf;
for(i=m;i!=0;i=pre[i])
{
sum=min(sum,map[pre[i]][i]);
}
for(i=m;i!=0;i=pre[i])
{
map[pre[i]][i]-=sum;
map[i][pre[i]]+=sum;
}
ans+=sum;
}
int main()
{
int i,l,a,k;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)scanf("%d",&have[i]);
memset(map,0,sizeof(map));
memset(pre,0,sizeof(pre));
for(l=1;l<=m;l++)
{
scanf("%d",&a);
while(a--)
{
scanf("%d",&k);
if(pre[k]==0)
map[0][l]+=have[k];
else
map[pre[k]][l]=inf;//为什么连边 ,因为打开后可以调整猪分配
而且 人来是有顺序的。
pre[k]=l;
}
scanf("%d",&map[l][m+1]);
}
m++;
ans=0;
while(bfs())EK();
printf("%d\n",ans);
}
}