首页 > 代码库 > 【BZOJ1280】Emmy卖猪pigs 最大流

【BZOJ1280】Emmy卖猪pigs 最大流

【BZOJ1280】Emmy卖猪pigs

Description

Emmy在一个养猪场工作。这个养猪场有M个锁着的猪圈,但Emmy并没有钥匙。顾客会到养猪场来买猪,一个接着一个。每一位顾客都会有一些猪圈的钥匙,他们会将这些猪圈打开并买走固定数目的猪。 所有顾客有的钥匙和他们需要买猪的数量在事先都告诉了Emmy,于是Emmy要订一个计划,使得卖出去的猪最多。 买卖的过程是这样的:一个顾客前来,并打开所有他可以打开的猪圈。然后Emmy从这些猪圈里牵出固定数目的猪卖给顾客(最多只能和顾客需要数相等),并可以重新安排这些开着的猪圈中的猪。 每个猪圈可以存放任意数目的猪。 写一个程序,使得Emmy能够卖出去尽可能多的猪。

Input

第一行有两个整数:M和N,表示猪圈数和顾客数。 第二行有M个整数,表示每个猪圈初始时有多少猪。 接下来的N行按照前来的次序描述了每一个顾客,每行的格式如下: A K1 K2…KA B A表示该顾客拥有的钥匙数,K1...KA表示每个钥匙所对应的猪圈,B表示该顾客需要购买的猪的数目。

Output

仅包含一个整数,即最多能卖出去的猪的数目。

Sample Input

3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6

Sample Output

7

HINT

1 ≤ M ≤ 1000
1 ≤ N ≤ 100

题解:经典的最大流模型,昨天发现在BZ上并没有A,于是重新写一发~

先建出这样一个naive的模型

1.将每个猪圈都拆成n个,然后从S向所有各自的第一个猪圈连边,容量为初始猪数,各自的猪圈向下一个顾客的对应猪圈连边,容量INF
2.从每个顾客需要的猪圈想顾客连边,容量INF,从顾客向T连边,容量为顾客要买的猪数,从顾客向这些猪圈连边,容量INF

发现所有跟中间状态的猪圈连的边都是INF,说明这些点根本没有必要存在,于是我们直接将中间状态的猪圈缩掉,改为直接从顾客向顾客连边就行了。

#include <cstdio>#include <cstring>#include <iostream>#include <queue>using namespace std;int m,n,cnt,ans,tot,S,T;int pre[1010],d[100000],next[1000000],val[1000000],head[100000],to[1000000];queue<int> q;int rd(){	int ret=0,f=1;	char gc=getchar();	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();	return ret*f;}void add(int a,int b,int c){	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;	to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;}int dfs(int x,int mf){	if(x==T)	return mf;	int i,k,temp=mf;	for(i=head[x];i!=-1;i=next[i])	{		if(d[to[i]]==d[x]+1&&val[i])		{			k=dfs(to[i],min(temp,val[i]));			if(!k)	d[to[i]]=0;			val[i]-=k,val[i^1]+=k,temp-=k;			if(!temp)	break;		}	}	return mf-temp;}int bfs(){	memset(d,0,sizeof(d));	while(!q.empty())	q.pop();	int i,u;	q.push(S),d[S]=1;	while(!q.empty())	{		u=q.front(),q.pop();		for(i=head[u];i!=-1;i=next[i])		{			if(!d[to[i]]&&val[i])			{				d[to[i]]=d[u]+1;				if(to[i]==T)	return 1;				q.push(to[i]);			}		}	}	return 0;}int main(){	m=rd(),n=rd();	int i,j,a,b,c;	S=0,T=n+m+1;	memset(head,-1,sizeof(head));	for(i=1;i<=m;i++)	pre[i]=i,add(S,i,rd());	for(i=1;i<=n;i++)	{		a=rd();		for(j=1;j<=a;j++)	b=rd(),add(pre[b],i+m,1<<30),pre[b]=i+m;		add(i+m,T,rd());	}	while(bfs())	ans+=dfs(S,1<<30);	printf("%d",ans);	return 0;}

【BZOJ1280】Emmy卖猪pigs 最大流