电场可以分为两个节点,节点间的流量上限是电场的最大发电量,用户可以分为两个节点,节点间的流量上限是用户的最大需求,再加上总的虚拟源点和总的虚拟汇点,虚拟源点到源点间的流量上限为INF,汇点到虚拟汇点间的流量上限为INF,接着就是最大流算法了:
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define INF 99999999
int S, T, n, np, nc, m, total;
struct Edge{
int from, to, capacity, flow;
Edge(int f, int t, int c) : from(f), to(t), capacity(c), flow(0){}
};
vector<Edge> edges; //all edges
vector<int> out[202];//edge indexes streching out of each node
bool vis[202];
int dis[202];
int cur[202];
bool input()
{
if(scanf("%d %d %d %d", &n, &np, &nc, &m) != 4) return false;
total = n + np + nc + 2;
S = total - 2;
T = total - 1;
int i, j, from, to, cap;
//initialize
edges.clear();
for(i = 0; i < total; ++i) out[i].clear();
//input edges
for(i = 0; i < m; ++i){
while(getchar() != '(') ;
scanf("%d,%d)%d", &from, &to, &cap);
out[from].push_back(edges.size());
edges.push_back(Edge(from, to, cap));
}
//input power stations
j = n;//index of added nodes
for(i = 0; i < np; ++i, ++j){
while(getchar() != '(') ;
scanf("%d)%d", &to, &cap);
//divide power station into two nodes with edge been its power capacity
out[j].push_back(edges.size());
edges.push_back(Edge(j, to, cap));
//connect S with power station with edge been INF
out[S].push_back(edges.size());
edges.push_back(Edge(S, j, INF));
}
//input consumers
for(i = 0; i < nc; ++i, ++j){
while(getchar() != '(') ;
scanf("%d)%d", &from, &cap);
//divide consumer into two nodes with edge been its consuming ability
out[from].push_back(edges.size());
edges.push_back(Edge(from, j, cap));
//connect j with T with edge been INF
out[j].push_back(edges.size());
edges.push_back(Edge(j, T, INF));
}
return true;
}
bool bfs()
{
//initialize
memset(vis, false, total);
queue<int> q;
q.push(S);
vis[S] = true;
dis[S] = 0;
//BFS to find augment path
while(!q.empty()){
int from = q.front(); q.pop();
for(int i = 0, n = out[from].size(); i < n; ++i){
Edge& e = edges[out[from][i]];
int to = e.to;
if(!vis[to] && e.capacity > e.flow){
vis[to] = true;
dis[to] = dis[from] + 1;
q.push(to);
}
}
}
//return flag if has augment path to meeting point
return vis[T];
}
int dfs(int from, int residual)
{
if(from == T || residual == 0) return residual;
int flow = 0, f;
for(int& i = cur[from]; i < out[from].size(); ++i){//这里是一个剪枝,从上次递归的边继续搜索,因为之前的边已经增广过了,不会再次进行增广了
Edge& e = edges[out[from][i]];
if(dis[from] + 1 == dis[e.to] &&
0 < (f = dfs(e.to, min(residual, e.capacity - e.flow)))
){
e.flow += f;
flow += f;
residual -= f;
if(residual == 0) break;//这里也是一个剪枝
}
}
return flow;
}
int maxFlow()
{
int flow = 0;
while(bfs()){
memset(cur, 0, total << 2);
flow += dfs(S, INF);
}
return flow;
}
int main()
{
while(input()) printf("%d\n", maxFlow());
return 0;
}