POJ-1149网络流

PIGS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 24426 Accepted: 11127
Description

Mirko works on a pig farm that consists of M locked pig-houses and Mirko can’t unlock any pighouse because he doesn’t have the keys. Customers come to the farm one after another. Each of them has keys to some pig-houses and wants to buy a certain number of pigs.
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 first line of input contains two integers M and N, 1 <= M <= 1000, 1 <= N <= 100, number of pighouses and number of customers. Pig houses are numbered from 1 to M and customers are numbered from 1 to N.
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

The first and only line of the output should contain the number of sold pigs.
Sample Input

3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 6
Sample Output

7

题意:就是一个养猪户卖猪,有M个房间,猪在房间里锁着,但是自己身上没有钥匙,买猪的人有N个,每个人手上有A个钥匙,分别是K1,K2,K3。。。KA房间的钥匙,所以可以买这些房间里面的猪,买猪的人需要B头猪。每一次来买猪的人买完后,养猪户都可以把其中一些房间的猪赶到另外一些房间里面去,这些房间都是这次买猪的人能打开的,而且每一间的房间可以装无限多的猪。
当时少看了两个条件,去看博客的时候看题意才懂的,一个是可以赶猪,另一个就是按照顺序来买猪,不然就会2号买猪先买,然后把3房间的猪赶到2房间,然后所有人都可以买到猪了,与样例答案不符。所以这个是按照顺序来买猪的。
问总共可以卖多少头猪

样例解释:3个房间,分别3 1 10 头猪。
3个买猪人,第一个2个钥匙,能开1 2 房间,需要2头猪
后面不解释
然后可以养猪户总共卖了7头猪
首先第一个买猪,买了1房间两头猪,然后养猪户把1房间剩下的1头猪赶到2房间,此时2房间有2头猪
第二个买猪的买3房间3头猪
第三个买2房间的2头猪
总共7头

思路:网络流,从源点到每个买猪人建边,流量是需要的猪的数量,每个买猪到能开的房间建边,流量是原来房间猪的数量,房间到汇点建边,流量是原来房间猪的数量。
第一个不解释,第二个是原来房间猪的数量,意思是:因为赶猪的条件,每个房间的猪可能会赶到其他房间,后来的买猪人会买到这些猪,但是把猪的剩余数量流到其他房间显得不太可能,**于是我们可以把有相同钥匙(即能开同一房间)的人建一条边,流量是INF,**这样,我们就可以转换一下,既然你可以把猪都赶到一个房间,那么就可以赶到我们相同的房间,那么我想买多少头猪,就可以通过你的途径来买,于是这条边是后来的指向先到的,流量是INF,因为还有后来的可以通过我的途径然后我通过你的途径来买猪~~(禁止套娃)~~ 第三个不解释,然后网络流套板子就可以了。
AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstdio>
using namespace std;
const int maxm=5e5+10;
const int maxn=3000;
const int INF=0x7f7f7f7f;
struct Edge{
	int next,v,val;
}map[maxm];
int head[maxn],sum;
int n,m,S,E,maxflow;
int num[maxn],dep[maxn],gap[maxn];

void Init()
{
	memset(map,0,sizeof(map));
	memset(head,-1,sizeof(head));
	sum=0;
	return ;
}
void addedge(int u,int v,int w)
{
	map[sum].v=v;
	map[sum].val=w;
	map[sum].next=head[u];
	head[u]=sum++;
	map[sum].v=u;
	map[sum].val=0;
	map[sum].next=head[v];
	head[v]=sum++;
	return ;
}
void bfs()
{
	memset(dep,-1,sizeof(dep));
	memset(gap,0,sizeof(gap));
	dep[E]=0;gap[0]=1;
	queue<int> q;
	q.push(E);
	while (!q.empty())
		{
			int u=q.front();
			q.pop();
			for (int i=head[u];i!=-1;i=map[i].next)
				{
					int v=map[i].v;
					if (dep[v]!=-1) continue;
					q.push(v);
					dep[v]=dep[u]+1;
					gap[dep[v]]++;
				}
		}
	//cout<<dep[S]<<"---------"<<endl;
	return ;
}
int dfs(int u,int flow)
{
	if (u==E)
		{
			maxflow+=flow;
			//cout<<maxflow<<" --== ==-- "<<endl;	
			//cout<<dep[S]<<endl;
			return flow;
		}
	int used=0;
	for (int i=head[u];i!=-1;i=map[i].next)
		{
			int v=map[i].v;
			if (map[i].val>0&&dep[v]+1==dep[u])
				{
					//cout<<u<<" -> "<<v<<" "<<map[i].val<<endl;
					int meta=dfs(v,min(map[i].val,flow-used));
					if (meta>0)
						{
							map[i].val-=meta;
							map[i^1].val+=meta;
							used+=meta;
						}
					if (used==flow) return used; 
				}
		}
	--gap[dep[u]];
	if (gap[dep[u]]==0) dep[S]=E+1;
	dep[u]++;
	gap[dep[u]]++;
	return used;
}
int ISAP()
{
	maxflow=0;
	bfs();
	while (dep[S]<E) dfs(S,INF);
	return maxflow;
}

int main(){
	vector<int> bri[maxn];
	int fl[maxn];
	int w,k;
	cin>>m>>n;
	S=0;E=n+m+1;
	Init();
	for (int i=1;i<=m;i++){
		scanf("%d",&fl[i]);	//记录每个房间原来猪的数量
		addedge(n+i,E,fl[i]);	//房间和汇点建边
	}
	for (int i=1;i<=n;i++){
		scanf("%d",&k);
		for (int j=1;j<=k;j++) {
			scanf("%d",&num[j]);	
			bri[num[j]].push_back(i);	//记录可以打开房间的买猪人
		}
		scanf("%d",&w);
		for (int j=1;j<=k;j++) 
			addedge(i,n+num[j],fl[num[j]]);//买猪人和房间建边
		addedge(S,i,w);		//源点和买猪人建边
	}
	for (int i=1;i<=m;i++){
		k=bri[i].size();
		for (int j=k-1;j>0;j--)
			addedge(bri[i][j],bri[i][j-1],INF);	//从后往前人人之间建边
	}
	int ans=ISAP();
	cout<<ans<<endl;
	return 0;
}
发布了46 篇原创文章 · 获赞 2 · 访问量 3195

猜你喜欢

转载自blog.csdn.net/z1164754004z/article/details/104597588