題意:這題差不多是最大流的模版題。
分析:建圖時需要加入一個源點和匯點,然後把所有電站和源點相連,邊的容量就是電站的發電量;把所有消費者和匯點相連,邊的容量就是消費者的消費量。建好網絡以後直接跑求最大流的算法即可。這題用的是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;
}