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

POJ 1459-Power Network(网络流_最大流)

2016-04-09 11:38 507 查看
Power Network
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice POJ
1459

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),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) <= 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


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.

题意: 图有 n 个节点,np 个节点是发电站,nc 个节点是消费站, m 条边,

形如 (u, v)z 表示 u-->v 最多传输电量为 m, p max(u)表示 u 点最多产

生电量为p,c max(u)表示 u 点最多消耗电量为 c。

本题求最多消耗多少电量。

思路: 因为是多源点汇点,所以人为加入一个总源点(0)和一个总汇点(n+1),

再从源点向每个发电站连线,权值为每个发电站最大发电量,将每个

消费站点加入汇点,权值为每个消费站最多消耗的电量,其它点的连接

由数据对的给出进行连接就行。因为题中点的下标是从 0 开始,我将它

们下标逐个加 1 处理成节点范围为(1--n)。

代码如下:

Dinic 算法(比较慢)

//因为是多源点汇点,所以加入一个源点(0)与汇点(n+1),dinic算法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 300
#define inf 0x3f3f3f3f
int level
, road

, n;
int bfs()//分层
{
memset(level, -1, sizeof(level));
level[0] = 0;
queue<int >q;
q.push(0);
while (!q.empty())
{
int o = q.front(); q.pop();
for (int i = 0; i <= n + 1; i++){
if (road[o][i] && level[i]<0)
{
level[i] = level[o] + 1;
q.push(i);
}
}
}
if (level[n + 1] > 0) return 1;
return 0;
}
int dfs(int s, int min_flow)//求增广路
{
int i, j, k, flow = 0;
if (s == n + 1) return min_flow;//找到汇点返回
for (i = 0; i <= n + 1; i++)
{
if (road[s][i] && level[s] + 1 == level[i]
&& (flow = dfs(i, min(min_flow, road[s][i]))))
{
road[s][i] -= flow;
road[i][s] += flow;
return flow;
}
}
return 0;
}
int main()
{
#ifdef OFFLINE
freopen("t.txt", "r", stdin);
#endif
int np, nc, m, i, j, k, a, b, c, tmp, ans;
while (~scanf("%d%d%d%d", &n, &np, &nc, &m))
{
memset(road, 0, sizeof(road));
while (m--){
while (getchar() != '(');
scanf("%d,%d)%d", &a, &b, &c);
road[a + 1][b + 1] += c;
}
while (np--){
while (getchar() != '(');
scanf("%d)%d", &a, &c);
road[0][a + 1] += c;//将源点(0)连接到发电点
}
while (nc--){
while (getchar() != '(');
scanf("%d)%d", &b, &c);
road[b + 1][n + 1] += c;//将消费者加入汇点(n+1)
}
ans = 0;
while (bfs())
{
while (tmp = dfs(0, inf))
ans += tmp;
}
printf("%d\n", ans);
}
return 0;
}


EK 算法(稍微快点)

//因为是多源点汇点,所以加入一个源点(0)与汇点(n+1),ek 算法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 300
#define inf 0x3f3f3f3f
int pre
, power
, road

, n;
void ek()
{
int i, j, k, max_flow = 0;
while (1)
{
memset(pre, -1, sizeof(pre));//边的前驱
memset(power, 0, sizeof(power));//传输的电
queue<int >q;
q.push(0);
power[0] = inf;
while (!q.empty())
{
int s = q.front();  q.pop();
for (i = 0; i <= n + 1; i++){
if (road[s][i] && !power[i]){
pre[i] = s;
power[i] = min(power[s], road[s][i]);
q.push(i);
}
}
if (power[n + 1])   break;//到汇点就先退出
}
if (!power[n + 1])  break;//到不了汇点退出
for (i = n + 1; i != 0; i = pre[i]){//更新流量
road[pre[i]][i] -= power[n + 1];//正减
road[i][pre[i]] += power[n + 1];//反加
}
max_flow += power[n + 1];//最大流
}
printf("%d\n", max_flow);
}
int main()
{
#ifdef OFFLINE
freopen("t.txt", "r", stdin);
#endif
int np, nc, m, i, j, k, a, b, c, tmp, ans;
while (~scanf("%d%d%d%d", &n, &np, &nc, &m))
{
memset(road, 0, sizeof(road));
while (m--){
while (getchar() != '(');
scanf("%d,%d)%d", &a, &b, &c);
road[a + 1][b + 1] += c;
}
while (np--){
while (getchar() != '(');
scanf("%d)%d", &a, &c);
road[0][a + 1] += c;//将源点(0)连接到发电点
}
while (nc--){
while (getchar() != '(');
scanf("%d)%d", &b, &c);
road[b + 1][n + 1] += c;//将消费者加入汇点(n+1)
}
ek();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: