1. 程式人生 > >[BZOJ1280]Emmy賣豬pigs

[BZOJ1280]Emmy賣豬pigs

通過 style 最大 程序 pop 初始 code 會有 void

題目大意:
Emmy在一個養豬場工作。這個養豬場有M個鎖著的豬圈,但Emmy並沒有鑰匙。顧客會到養豬場來買豬,一個接著一個。每一位顧客都會有一些豬圈的鑰匙,他們會將這些豬圈打開並買走固定數目的豬。 所有顧客有的鑰匙和他們需要買豬的數量在事先都告訴了Emmy,於是Emmy要訂一個計劃,使得賣出去的豬最多。 買賣的過程是這樣的:一個顧客前來,並打開所有他可以打開的豬圈。然後Emmy從這些豬圈裏牽出固定數目的豬賣給顧客(最多只能和顧客需要數相等),並可以重新安排這些開著的豬圈中的豬。 每個豬圈可以存放任意數目的豬。 寫一個程序,使得Emmy能夠賣出去盡可能多的豬。
解題思路:
最大流。
從源向豬圈連容量為初始豬的數量的邊。

對於每一個顧客可以開的豬圈,若該豬圈被之前的顧客打開過,則從最後打開過這個豬圈的顧客向這個顧客連容量為inf的邊,否則從這個豬圈向該顧客連容量inf的邊。
對於每個顧客,向匯點連容量為inf的邊。
為什麽這麽連邊呢?
首先,第一個打開豬圈的顧客拿豬是沒問題的。
其次,若一個豬圈已經被一個顧客開了,那麽這個顧客可以得到原來那個顧客打開的其他豬圈的豬(可以通過交換得到),更早打開的也可以通過顧客鏈傳遞過來。

C++ Code:

#include<cstdio>
#include<cctype>
#include<cctype>
#include<cstring>
#include<queue>
const int S=0,T=2330,inf=0x3f3f3f3f;
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
int n,m,head[2333],cnt=1,pig[2333]={0},level[2333],iter[2333];
struct edge{
	int to,nxt,cap;
}e[400005];
inline void addedge(int u,int v,int t){
	e[++cnt]=(edge){v,head[u],t};
	head[u]=cnt;
	e[++cnt]=(edge){u,head[v],0};
	head[v]=cnt;
}
std::queue<int>q;
void bfs(){
	level[S]=1;
	for(q.push(S);!q.empty();){
		int u=q.front();
		q.pop();
		for(int i=head[u];~i;i=e[i].nxt)
		if(e[i].cap&&!~level[e[i].to]){
			level[e[i].to]=level[u]+1;
			q.push(e[i].to);
		}
	}
}
inline int min(int a,int b){return a<b?a:b;}
int dfs(int u,int f){
	if(!f||u==T)return f;
	for(int& i=iter[u];~i;i=e[i].nxt)
	if(e[i].cap&&level[e[i].to]>level[u]){
		int d=dfs(e[i].to,min(f,e[i].cap));
		if(d){
			e[i].cap-=d;
			e[i^1].cap+=d;
			return d;
		}else level[e[i].to]=-1;
	}
	return 0;
}
int dinic(){
	for(int flow=0,f;;){
		memset(level,-1,sizeof pig);
		if(bfs(),!~level[T])return flow;
		memcpy(iter,head,sizeof pig);
		while(f=dfs(S,inf))flow+=f;
	}
}
int main(){
	cin>>n>>m;
	memset(head,-1,sizeof head);
	for(int i=1,p;i<=n;++i){
		cin>>p;
		addedge(S,i,p);
	}
	for(int i=1,p;i<=m;++i){
		const int id=n+i;
		cin>>p;
		for(int k;p--;){
			cin>>k;
			if(pig[k])addedge(pig[k],id,inf);else
			addedge(k,id,inf);
			pig[k]=id;
		}
		cin>>p;
		addedge(id,T,p);
	}
	cout<<dinic()<<endl;
	return 0;
}

[BZOJ1280]Emmy賣豬pigs