题意:这题差不多是最大流的模版题。
分析:建图时需要加入一个源点和汇点,然后把所有电站和源点相连,边的容量就是电站的发电量;把所有消费者和汇点相连,边的容量就是消费者的消费量。建好网络以后直接跑求最大流的算法即可。这题用的是ford-fulkerson方法,刚开始用dfs最增广路超时了,换成bfs找增广路AC。
PS:现在才知道ford-fulkerson只是一种方法,而并不是一种算法。用bfs找增广路就是Edmonds-Karp算法,简称EK。
以下附上代码:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cmath>
#include <stack>
#include <queue>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 205;
const int inf = 1000000000;
struct arc
{
int c,f;
};
int n,np,nc,m;
arc edge[maxn][maxn];
int al[maxn];
int p[maxn];
bool vis[maxn];
//这个网络以n+1为源点n为汇点
void input()
{
int i,j;
int u,v,c;
for(i = 0; i <= n+1; i++){
for(j = 0; j <= n+1; j++){
edge[i][j].c = edge[i][j].f = 0;
}
}
for(i = 0; i <= n+1; i++) vis[i] = 0;
for(i = 0; i < m; i++){
scanf(" (%d,%d)%d",&u,&v,&c);
edge[u][v].c = c;
}
//源点
for(i = 0;i < np; i++){
scanf(" (%d)%d",&u,&c);
edge[n+1][u].c = c;
}
//汇点
for(i = 0; i < nc; i++){
scanf(" (%d)%d",&u,&c);
edge[u][n].c = c;
}
}
int bfs()
{
int i;
int u,v;
queue<int> q;
fill(vis,vis+n+2,0);
//bfs寻找增广路
al[n+1] = inf;
q.push(n+1);
vis[n+1] = 1;
while(!q.empty()){
u = q.front(); q.pop();
for(i = 0; i <= n; i++){
if(vis[i]) continue;
//正向且未满
if(edge[u][i].c && edge[u][i].f < edge[u][i].c){
vis[i] = 1;
al[i] = min(al[u],edge[u][i].c - edge[u][i].f);
p[i] = u;
q.push(i);
}
//反向且有流量
else if(edge[i][u].c && edge[i][u].f){
vis[i] = 1;
al[i] = min(al[u],edge[i][u].f);
p[i] = -u;
q.push(i);
}
}//for i
if(vis[n]) break;
}//while
if(!vis[n]) return 0;
//增广
int t = n;
int alpha = al[n];
while(t != n+1){
if(p[t] >= 0) edge[p[t]][t].f += alpha;
else edge[t][-p[t]].f -= alpha;
t = abs(p[t]);
}
return alpha;
}
int solve()
{
int maxFlow = 0;
int flow;
while(flow = bfs()) maxFlow += flow;
return maxFlow;
}
int main()
{
while(scanf("%d%d%d%d",&n,&np,&nc,&m) == 4){
input();
printf("%d\n",solve());
}
return 0;
}