这段时间要沉迷刷题一段时间了,就让优快云陪我一起吧!
一、题目大意
这道题叙述的格外的麻烦,这里我就直接抽象简化的说一下了。题目大意是给你一个已知的网络,n个顶点,m条边,其中有np个发电站(只能产生电),nc的消耗站(只能消耗电),剩下的就是传输站(只能传输站)了。然后让你求这个网络的最大流。
二、题目思路以及AC代码
题目都说的很清楚了,就是求最大流的问题。但是这里是多源点多汇点求最大流的问题,不要怕,对于这个问题来说,我们可以考虑建立"超级源点"和"超级汇点","超级源点"用于给各个发电站供电,此时发电站也就相当于传输站。"超级汇点"用于消耗所有由消耗站传来的电,此时的消耗站也就相当于传输站。这样的话,整个问题就是一个最大流的模板题啦!
下面给出AC代码:
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#define MAXN 110
#define INF 1000000
using namespace std;
int edges[MAXN][MAXN];
int pre[MAXN];
bool vis[MAXN];
int n, np, nc, nd, m;
void init() {
for (int i = 0; i < MAXN; i++) {
for (int j = 0; j < MAXN; j++) {
edges[i][j] = 0;
}
}
}
int Min(int a, int b) {
return a > b ? b : a;
}
void update(int t, int delta) {
for (int i = t; pre[i] != -1; i = pre[i]) {
edges[pre[i]][i] -= delta;
edges[i][pre[i]] += delta;
}
}
int find_path_bfs(int s, int t){
memset(pre, -1, sizeof(pre));
memset(vis, false, sizeof(vis));
int min = INF;
queue<int> q;
vis[s] = true;
q.push(s);
while (!q.empty()) {
int cur = q.front(); q.pop();
if (cur == t) break;
for (int i = 0; i < n + 2; i++) {
if (!vis[i] && edges[cur][i]) {
vis[i] = true;
q.push(i);
pre[i] = cur;
}
}
}
if (pre[t] == -1) return 0;
for (int i = t; pre[i] != -1; i = pre[i]) {
min = Min(edges[pre[i]][i], min);
}
return min;
}
int EK(int s, int t) {
int new_flow = 0;
int max_flow = 0;
while (new_flow = find_path_bfs(s, t)) {
update(t, new_flow);
max_flow += new_flow;
}
return max_flow;
}
char str[100];
int main()
{
while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF) {
init();
int u, v, content;
for (int i = 0; i < m; i++) {
scanf("%s", str);
sscanf(str, "(%d,%d)%d", &u, &v, &content);
edges[u][v] += content;
}
for (int i = 0; i < np; i++) {
scanf("%s", str);
sscanf(str, "(%d)%d", &v, &content);
edges[n][v] += content;
}
for (int i = 0; i < nc; i++) {
scanf("%s", str);
sscanf(str, "(%d)%d", &u, &content);
edges[u][n + 1] += content;
}
printf("%d\n", EK(n, n + 1));
}
return 0;
}