您的位置:首页 > 理论基础 > 计算机网络

poj1459 Power Network网络流最大流基础题

2012-08-07 21:00 127 查看
此题纯粹最大流没有变形,关键看懂英文

此题是网络流最大流关键是构图和sscanf的运用。此题是多起点多汇点。处理这类问题应该建立超级原点和超级汇点,原来的源点容量和汇点容量处理成超级源点到个源点的容量,各汇点的容量处理为汇点到超级汇点的容量

Power Network

Time Limit: 2000MSMemory Limit: 32768K
Total Submissions: 17996Accepted: 9509
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) <= pmax(u) of power, may consume an amount 0 <= c(u) <= min(s(u),cmax(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) <= lmax(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 pmax(u)=y. The label x/y of consumer u shows that c(u)=x and cmax(u)=y. The label x/y of power transport line (u,v) shows that l(u,v)=x and lmax(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 lmax(u,v). Follow np doublets (u)z, where u is the identifier of a power station and 0 <= z
<= 10000 is the value of pmax(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 cmax(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

Hint
The sample input contains two data sets. The first data set encodes a network with 2 nodes, power station 0 with pmax(0)=15 and consumer 1 with cmax(1)=20, and 2 power transport lines with lmax(0,1)=20
and lmax(1,0)=10. The maximum value of Con is 15. The second data set encodes the network from figure 1.
Source
Southeastern Europe 2003
翻译:

一个电网由电力运输线连接的节点(发电站,消费者和中转)。一个节点u可提供数额s(U)>=0电力,可能会产生数额为0<= P(U)<= Pmax(U)的电力,可能会消耗数额0<= C(U) <= MIN(s(U),Cmax(U))的电力,并可能传递的数额D(U)=s(U)+ P(U)-C(U)的电力。以下限制适用于:C(U)= 0的任何电站,P(U)=0的任何消费者,P(U)= C(U)= 0的任何中转站。有至多有一个从节点u到节点v的净电力运输线(U,V),它输送的数额0<= L(U,V)<= Lmax的(U,V)电源传递由u到V.让CON=Σuc(U)是净消耗的功率。问题是要计算最大值的CON。

一个例子是在图1。标号x/y电站ü显示了:P(U)= x和Pmax(U)= Y。标签的x / y的消费者ü显示,C(U)= X和Cmax(U)= Y。电力运输线的X / Y(U,V)的标签显示了。l(U,V)= x和Lmax的(U,V)=y。消耗的功率是CON= 6。请注意,有网络的其他可能的状态,但CON值不能超过6。

有几个数据输入集。每个数据集编码一个电源网络。它开始四个整数:0<= N<= 100(节点),0 <= NP<= N(电站),0<= NC<= N(消费者),0<= M <= N^ 2 (电力运输线)y。接下来m个数据三个数(U,V)Z,U和V是节点标识符(从0开始)且0<= Z <= 1000 Lmax的值(U,V)。按照NP双峰(U)Z,其中u是一个发电站和0的标识符<= Z<= 10000 Pmax(U)的价值。数据集结束NC两个数(U)z,其中u是消费者和0的标识符<=
Z<= 10000的Cmax值(U)。所有输入的数字都是整数。除外(U,V)Z三胞胎(U)Z双峰,其中不包含空格,空格可以发生自由输入。输入数据的一个文件结束与终止,是正确的。

谷歌翻译的自己改了改,大概看得懂就可以了见谅啊。

#define VMAX 201
#include<iostream>
using namespace std;
int c[VMAX][VMAX]; //容量
int n, m;       //分别表示图的边数和顶点数       
int EK( int s, int t )           // 输入源点和汇点
{   
	int p, q, queue[VMAX], u, v, pre[VMAX], flow= 0, aug;
	while(true)
	{  
		memset(pre,-1,sizeof(pre));        //记录父节点
		for( queue[p=q=0]=s; p<=q; p++ )    //广度优先搜索  p是头指针,q是尾指针 初始化皆为0 
		{
			u= queue[p];
			//原点是s     汇点是t    n是顶点    m是边 
			for( v=0; v<n+2&&pre[t]<0; v++ )
				if( c[u][v]>0 && pre[v]<0 ) //如果两者u到v连通 且v的父节点没有记录 则记录v的父节点是u,且入队  
     				pre[v]=u, queue[++q]=v;
            //找完 汇点的父节点已经找到了 
			if( pre[t]>=0 )    
				break;
		}
		//上面bfs是找增广路的 
        if( pre[t]<0 )    break;        //不存在增广路(while退出条件,直至没有增广路就找到最大流了) 
        aug= 0x7fffffff;    //记录最小残留容量
        for( u=pre[v=t]; v!=s; v=u,u=pre[u] )//u赋值给v u=u的父亲节点,那么u,v就是一个连通量 
            if(c[u][v]<aug)    aug=c[u][v];   //找最小的残留量 
        for( u=pre[v=t]; v!=s; v=u,u=pre[u] ) //更新记录流量 
            c[u][v]-=aug, c[v][u]+=aug;    //u到v是正流量用-=   v到u是反流量用+= 
        flow+= aug;
    }
    return flow; 
}  
int main()
{ 
	int i,a,b,va;
 	int np,nc;
 	char ss[50];
	char ch; 
	//while(cin>>n>>np>>nc>>m)//n个节点,m个边 
	while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
	{
		memset(c,0,sizeof(c));  
		for(i=0;i<m;i++)
		{ 
			//cin>>ch>>a>>ch>>b>>ch>>va;
			scanf("%s",ss);
            sscanf(ss,"(%d,%d)%d",&a,&b,&va);//sscanf的运用应该看看哦! 
			c[a+1][b+1]=va;//两点间可能有多条路径,把权值相加
		}
		for(i=0;i<np;i++)
		{
			//cin>>ch>>a>>ch>>b;
			scanf("%s",ss);
            sscanf(ss,"(%d)%d",&a,&b);
			c[0][a+1]=b;
		}
		for(i=0;i<nc;i++)
		{
			//cin>>ch>>a>>ch>>b;
			scanf("%s",ss);
            sscanf(ss,"(%d)%d",&a,&b);
			c[a+1][n+1]=b;
		}
		printf("%d\n",EK(0,n+1));
	   //	cout<<Edmonds_Karp(0,n+1)<<endl;//从源点为0,汇点为顶点数n+1;        
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: