这张网每秒最多过多少水
一张管道网,0 号是水源、6 号是出口,cap[u][v] 是 u→v 这根管子每秒最多能过多少水。
运行下面这段程序:
#include <algorithm>
#include <climits>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <utility>
#include <vector>
using namespace std;
// 管道网:0 号是水源、6 号是出口,cap[u][v] 是 u→v 这根管子每秒最多过多少水(0 表示没有这根管子)
using Cap = vector<vector<int>>;
Cap make_cap() {
Cap c(7, vector<int>(7, 0));
c[0][1] = 6; c[0][2] = 5; c[1][3] = 4; c[1][4] = 2; c[2][4] = 5;
c[3][6] = 3; c[4][3] = 2; c[4][5] = 4; c[5][6] = 5;
return c;
}
const Cap CAP = make_cap();
// Edmonds-Karp:反复用 BFS 找一条每段都还有余量的路,把它最细的那一段灌满;res 带回残量图
int maxflow(Cap cap, int s, int t, Cap* res = nullptr) {
int n = cap.size(), flow = 0;
for (int round = 0; round < 50; round++) {
vector<int> par(n, -1);
par[s] = s;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v = 0; v < n; v++) {
if (cap[u][v] > 0 && par[v] == -1) {
par[v] = u;
q.push(v);
}
}
}
if (par[t] == -1) break;
int b = INT_MAX;
for (int v = t; v != s; v = par[v]) b = min(b, cap[par[v]][v]);
for (int v = t; v != s; v = par[v]) {
cap[par[v]][v] -= b;
cap[v][par[v]] += b;
}
flow += b;
}
if (res) *res = cap;
return flow;
}
int main() {
cout << maxflow(CAP, 0, 6) << endl;
}
(本题用 g++ -std=c++17 -O0 编译。)
全部评论