1. 程式人生 > >【BZOJ1280】Emmy賣豬pigs 最大流

【BZOJ1280】Emmy賣豬pigs 最大流

mes 事先 == 經典 include sof 打開 鑰匙 zoj

【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 最大流