POJ 1459 Power Network / HIT 1228 Power Network / UVAlive 2760 Power Network / ZOJ 1734 Power Network / FZU 1161 (网络流,最大流)

POJ 1459 Power Network / HIT 1228 Power Network / UVAlive 2760 Power Network / ZOJ 1734 Power Network / FZU 1161 (网络流,最大流)

Description

A power network consists of nodes (power stations, consumers and dispatchers) connected by power transport lines. A node u may be supplied with an amount s(u) >= 0 of power, may produce an amount 0 <= p(u) <= p max(u) of power, may consume an amount 0 <= c(u) <= min(s(u),c max(u)) of power, and may deliver an amount d(u)=s(u)+p(u)-c(u) of power. The following restrictions apply: c(u)=0 for any power station, p(u)=0 for any consumer, and p(u)=c(u)=0 for any dispatcher. There is at most one power transport line (u,v) from a node u to a node v in the net; it transports an amount 0 <= l(u,v) <= l max(u,v) of power delivered by u to v. Let Con=Σ uc(u) be the power consumed in the net. The problem is to compute the maximum value of Con.
此处输入图片的描述
An example is in figure 1. The label x/y of power station u shows that p(u)=x and p max(u)=y. The label x/y of consumer u shows that c(u)=x and c max(u)=y. The label x/y of power transport line (u,v) shows that l(u,v)=x and l max(u,v)=y. The power consumed is Con=6. Notice that there are other possible states of the network but the value of Con cannot exceed 6.

Input

There are several data sets in the input. Each data set encodes a power network. It starts with four integers: 0 <= n <= 100 (nodes), 0 <= np <= n (power stations), 0 <= nc <= n (consumers), and 0 <= m <= n^2 (power transport lines). Follow m data triplets (u,v)z, where u and v are node identifiers (starting from 0) and 0 <= z <= 1000 is the value of l max(u,v). Follow np doublets (u)z, where u is the identifier of a power station and 0 <= z <= 10000 is the value of p max(u). The data set ends with nc doublets (u)z, where u is the identifier of a consumer and 0 <= z <= 10000 is the value of c max(u). All input numbers are integers. Except the (u,v)z triplets and the (u)z doublets, which do not contain white spaces, white spaces can occur freely in input. Input data terminate with an end of file and are correct.

Output

For each data set from the input, the program prints on the standard output the maximum amount of power that can be consumed in the corresponding network. Each result has an integral value and is printed from the beginning of a separate line.

Sample Input

2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20
7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7
(3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5
(0)5 (1)2 (3)2 (4)1 (5)4

Sample Output

15
6

Http

POJ:https://vjudge.net/problem/POJ-1459
HIT:https://vjudge.net/problem/HIT-1228
UVAlive:https://vjudge.net/problem/UVALive-2760
ZOJ:https://vjudge.net/problem/ZOJ-1734
FZU:https://vjudge.net/problem/FZU-1161

Source

网络流,最大流

题目大意

给定一个能量网络,这个网络中有供能的机械,也有接收能量的机械,还有用作能量中转的机械。机械之间有能量管道相连,每一个管道都有一个能量上限。现在给出每一个供能机械的最大供能和每一个接收能量机械的最多需要能量,求最多能给所有接收能量的机械提供多少能量。

解决思路

这种长的英文题是锻炼英语阅读能力最好的机会
首先解释一下题意。题目中给出了三种机械,内容如题目大意中所述,求最大能量供应。输入中,先输入的四个整数分别是总机械数,供能机械数,接收能量机械数,能量管道数。接着m个是能量管道(u,v)w代表从u到v有一条上限为w的单向管道。再接着是np个供能机械,(u)w代表编号为u的供能机械能最多提供w的能量。最后是nc个接收能量机械,(u)w代表编号为u的最多接收w能量。
我们设立源点和汇点。对于每一个供能机械,从源点连出一条边到它,容量就为其能提供的最大能量数。对于每一个接收能量的机械,连一条边到汇点,容量就为其要接收的最大能量。其它的边就是题中的能量管道,容量就是能量管道的上限。这样跑一边最大流即可。
关于最大流,这里使用Dinic实现,可以参考我的这篇文章

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxN=300;
const int maxM=maxN*maxN*2;
const int inf=2147483647;

class Edge
{
public:
	int u,v,flow;
};

int n,np,nc;//总机械数,供能机械数,收能机械数
int m;//能量管道数
int cnt=-1;
int Head[maxN];
int Next[maxM];
Edge E[maxM];
int depth[maxN];
int cur[maxN];
int Q[maxN];

void Add_Edge(int u,int v,int flow);
bool bfs();
int dfs(int u,int flow);

int main()
{
	while (cin>>n>>np>>nc>>m)//多组数据
	{
		cnt=-1;//每次先要清空
		memset(Head,-1,sizeof(Head));
		while (m--)//读入边
		{
			int u,v,w;
			while (getchar()!='(');//注意这里读入时要特殊处理一下
			scanf("%d,%d)%d",&u,&v,&w);
			Add_Edge(u+1,v+1,w);
		}
		while (np--)//读入供能机械
		{
			int u,maxflow;
			while (getchar()!='(');
			scanf("%d)%d",&u,&maxflow);
			Add_Edge(0,u+1,maxflow);
		}
		while (nc--)//读入收能机械
		{
			int u,maxflow;
			while (getchar()!='(');
			scanf("%d)%d",&u,&maxflow);
			Add_Edge(u+1,n+1,maxflow);
		}
		/*for (int i=0;i<=n+1;i++)
		{
			for (int j=Head[i];j!=-1;j=Next[j])
				cout<<i<<" "<<E[j].v<<" "<<E[j].flow<<endl;
			cout<<endl;
		}
		//*/
		int Ans=0;//求解最大流,Dinic算法
		while (bfs())
		{
			for (int i=0;i<=n+1;i++)
				cur[i]=Head[i];
			while (int di=dfs(0,inf))
				Ans+=di;
		}
		printf("%d\n",Ans);
	}
	return 0;
}

void Add_Edge(int u,int v,int flow)
{
	cnt++;
	Next[cnt]=Head[u];
	Head[u]=cnt;
	E[cnt].u=u;
	E[cnt].v=v;
	E[cnt].flow=flow;

	cnt++;
	Next[cnt]=Head[v];
	Head[v]=cnt;
	E[cnt].u=v;
	E[cnt].v=u;
	E[cnt].flow=0;
}

bool bfs()
{
	memset(depth,-1,sizeof(depth));
	int h=1,t=0;
	depth[0]=1;
	Q[1]=0;
	do
	{
		t++;
		int u=Q[t];
		for (int i=Head[u];i!=-1;i=Next[i])
		{
			int v=E[i].v;
			if ((E[i].flow>0)&&(depth[v]==-1))
			{
				depth[v]=depth[u]+1;
				h++;
				Q[h]=v;
			}
		}
	}
	while (t!=h);
	if (depth[n+1]==-1)
		return 0;
	return 1;
}

int dfs(int u,int flow)
{
	if (u==n+1)
		return flow;
	for (int &i=cur[u];i!=-1;i=Next[i])
	{
		int v=E[i].v;
		if ((depth[v]==depth[u]+1)&&(E[i].flow>0))
		{
			int di=dfs(v,min(flow,E[i].flow));
			if (di>0)
			{
				E[i].flow-=di;
				E[i^1].flow+=di;
				return di;
			}
		}
	}
	return 0;
}
posted @ 2017-08-16 20:10  SYCstudio  阅读(443)  评论(2编辑  收藏  举报