题意: 给定np个发电站, nc个消费者, m条从u流到v的边, 其权值为边的最大容量, 求解, 消费者总的最大可用电量
求解: 增加两个点:源点以及汇点, 源点指向所有的发电站(即给发电站提供电量, 但是每个发电站最大接收量已被限制), 所有的消费者指向汇点(即消费者所能用的电量全部汇聚到该汇点上,每个消费者能用的电量有最大限制), 构建网络流模型, 用EdmondsKarp算法求解
code:
/*
s(u) u被提供的能量数
p(u) 0<=p(u)<=Pmax(u) u产生的能量数
c(u) u消耗的能量数 (0<=c(u)<=minn(s(u), Cmax(u)))
d(u) u向外传递的能量数 = s(u)+p(u)-c(u)
每个发电站 c(u) = 0;
每个消费者(用电者) p(u)=0;
每个调度员 c(u)=0 && p(u)=0;
u到v至多一条电力通路
l(u, v) u传送到v的总能量数
Con = EuC(u), 消耗总和
求Con最大值
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 205;
const int inf = 0x3f3f3f3f3f;
int n, np, nc, m, s, e;//s->源点, e->汇点
//n:nodes
//np: power stations 发电站数
//nc: consumers 消费者数
//m: 电力通路数
int edge[maxn][maxn];// u-v之间电力通路传送最大值
int flow[maxn], vis[maxn];
int pre[maxn];
//找出所有增广路, 每找出一条就在各个边上去掉汇点上所获得的能量
int bfs(){
int i, v;
queue<int>que;
memset(flow, -1, sizeof(flow));
memset(vis, 0, sizeof(vis));
while(!que.empty()) que.pop();
que.push(s);
vis[s] = 1;
flow[s] = inf;
pre[s] = s;
while(!que.empty()){
v = que.front();
que.pop();
for(i=s; i<=e; i++){
if(vis[i]&&edge[v][i]){
vis[i] = 1;
flow[i] = min(flow[v], edge[v][i]);
que.push(i);
pre[i] = v;
}
}
}
if(flow[e]!=-1){
return flow[e];
} else {
return 0;
}
}
int EdmondsKarp(){
int i, MIN;
int maxflow = 0;
while(MIN=bfs()){
for(i=e; i!=s; i=pre[i]){
edge[pre[i]][i] -= MIN;//正向边
edge[i][pre[i]] += MIN;//反向边
}
maxflow += MIN;
}
return maxflow;
}
int main()
{
int i, j, k;
char c;
while(~scanf("%d %d %d %d%*c", &n, &np, &nc, &m)){
s=0, e=n+1;
memset(edge, 0, sizeof(edge));
int x, y, z;
for(i=1; i<=m; i++){
while((c=getchar())!='(');
scanf("%d,%d)%d", &x, &y, &z);
if(x==y) continue;
edge[x+1][y+1]+=z;
}
for(i=1; i<=np; i++){
while((c=getchar())!='(');
scanf("%d)%d", &x, &z);
edge[s][x+1] = z;//源点与每个发电站建立联系
}
for(i=1; i<=nc; i++){
while((c=getchar())!='(');
scanf("%d)%d", &x, &z);
edge[x+1][e] = z;//汇点与每个消费者建立联系
}
printf("%d\n", EdmondsKarp());
}
return 0;
}