题目链接:
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 }