POJ-1459 Power Network---最大流

题目链接:

https://cn.vjudge.net/problem/POJ-1459

题目大意:

简单的说下题意(按输入输出来讲,前面的描述一堆的rubbish,还用来误导人),给你n个点,其中有np个是能提供电力的点,nc个是能消费电力的点,剩下的点(n-np-nc)是中转战即不提供电力也不消费电力,点与点之间是有线路存在的,有m条线路,每条线路有最多运载限定。
前4个数据就是有n个点,np个供电点,nc个消费点,m条线路,接来题目先给出的是m条线路的数据,(起点,终点)最多运载量,然后是np个供电点的数据(供电点)最多供电量,接着就是nc个消费点的数据(消费点)最多消费电量。
题目要我们求出给定的图最大能消费的总电量(就是求最大流)

解题思路:

传送门:网络流

供电点有提供功能,那么供电点就可以当成源点,同样消费点有消费功能,可以当成汇点。
由于这题有多个供电点和消费点,我们可以增加两个点,一个超级源点和一个超级汇点。
把所有的供电点都当成是由超级源点提供电量的,所有的消费点都将消费电量转移到超级汇点上,这样就相当于转换成一个基本的网络流求最大流的题。
超级源点与供电点有一条边,边的值为供电点最大能提供的电量,消费点与超级汇点有一条边,边的值为消费点最大能消费的电量。

增加源点汇点这一技巧很常用。

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 using namespace std;
 7 const int INF = 0x3f3f3f3f;
 8 const int maxn = 100 + 10;
 9 struct edge
10 {
11     int u, v, c, f;
12     edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
13 };
14 vector<edge>e;
15 vector<int>G[maxn];
16 int a[maxn];//找增广路每个点的水流量
17 int p[maxn];//每次找增广路反向记录路径
18 void init(int n)
19 {
20     for(int i = 0; i <= n; i++)G[i].clear();
21     e.clear();
22 }
23 void addedge(int u, int v, int c)
24 {
25     e.push_back(edge(u, v, c, 0));
26     e.push_back(edge(v, u, 0, 0));
27     int m = e.size();
28     G[u].push_back(m - 2);
29     G[v].push_back(m - 1);
30 }
31 int Maxflow(int s, int t)
32 {
33     int flow = 0;
34     for(;;)//每次寻找增广路
35     {
36         memset(a, 0, sizeof(a));//初始化每个节点的流量均为0,源点流量为INF
37         a[s] = INF;
38         queue<int>q;
39         q.push(s);
40         while(!q.empty())
41         {
42             int u = q.front();
43             q.pop();
44             for(int i = 0; i < G[u].size(); i++)
45             {
46                 edge &now = e[G[u][i]];
47                 int v = now.v;
48                 if(!a[v] && now.c > now.f)//v点还未流经,且这条路还没流满
49                 {
50                     p[v] = G[u][i];//反向记录
51                     a[v] = min(a[u], now.c - now.f);
52                     q.push(v);
53                 }
54             }
55             if(a[t])break;//已经到汇点
56         }
57         if(!a[t])break;//已经找不到增广路
58         for(int u = t; u != s; u = e[p[u]].u)
59         {
60             e[p[u]].f += a[t];
61             e[p[u] ^ 1].f -= a[t];
62         }
63         flow += a[t];
64     }
65     return flow;
66 }
67 int main()
68 {
69     int n, np, nc, m;//分别表示点数,电站数,居民数,边数
70     while(cin >> n >> np >> nc >> m)
71     {
72         int s = n, t = n + 1;
73         init(t);
74         int u, v, c;
75         for(int i = 0; i < m; i++)//建边
76         {
77             while(getchar() != '(');//读取左括号
78             scanf("%d,%d)%d", &u, &v, &c);
79             addedge(u, v, c);
80         }
81         for(int i = 0; i < np; i++)//对于每个电站,从源点到电站点连一条边,权值为电站发电值
82         {
83             while(getchar() != '(');
84             scanf("%d)%d", &v, &c);
85             addedge(s, v, c);
86         }
87         for(int i = 0; i < nc; i++)//对于每个居民,从居民点到汇点连一条边,权值是居民用电值
88         {
89             while(getchar() != '(');
90             scanf("%d)%d", &u, &c);
91             addedge(u, t, c);
92         }
93         cout<<Maxflow(s, t)<<endl;
94     }
95     return 0;
96 }

 

posted @ 2018-04-16 20:42  _努力努力再努力x  阅读(191)  评论(0编辑  收藏  举报