std::vector<bool> minCut() { std::vector<bool> c(n); for (int i = 0; i < n; i++) { c[i] = (h[i] != -1); } return c; }
这里返回的布尔数组 c 表示每个顶点是否在源点 s 的可达集合 S 中。根据最大流最小割定理,从 S 到 T(不可达部分)的边就是最小割边。虽然函数本身只返回了 S 集合的信息,但你可以通过扫描所有边,找出那些一端在 S(c[u] == true)而另一端在 T(c[v] == false)的边,从而得到具体的割边。
boolbfs(int s, int t){ dep.assign(n, -1); queue<int> q; q.push(s); dep[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (auto i : g[u]) { auto [v, c] = e[i]; if (c > 0 && dep[v] == -1) { dep[v] = dep[u] + 1; q.push(v); if (v == t) returntrue; } } } returnfalse; }
T dfs(int u, int t, T flow){ if (u == t) return flow; T sum = 0; for (int i = cur[u]; i < g[u].size(); i++) { cur[u] = i; int j = g[u][i]; auto& [v, c] = e[j]; if (dep[v] == dep[u] + 1 && c > 0) { T f = dfs(v, t, min(c, flow)); e[j].cap -= f; e[j ^ 1].cap += f; sum += f; flow -= f; if (flow == 0) break; } } if (sum == 0) dep[u] = 0; return sum; }
T dinic(int s, int t){ T F = 0; while (bfs(s, t)) { cur.assign(n, 0); F += dfs(s, t, std::numeric_limits<T>::max()); } return F; }
vector<int> minCut(){ vector<int> c(n); for (int i = 0; i < n; i++) { c[i] = (dep[i] == -1) ? 0 : 1; } return c; }
voidadd(int u, int v, T c){ g[u].push_back(int(e.size())); e.emplace_back(v, c); g[v].push_back(int(e.size())); e.emplace_back(u, 0); } };
boolbfs(int s, int t){ dep.assign(n, -1); queue<int> q; q.push(s); dep[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); for (auto i : g[u]) { auto [v, c] = e[i]; if (c > 0 && dep[v] == -1) { dep[v] = dep[u] + 1; q.push(v); if (v == t) returntrue; } } } returnfalse; }
T dfs(int u, int t, T flow){ if (u == t) return flow; T sum = 0; for (int i = cur[u]; i < g[u].size(); i++) { cur[u] = i; int j = g[u][i]; auto& [v, c] = e[j]; if (dep[v] == dep[u] + 1 && c > 0) { T f = dfs(v, t, min(c, flow)); e[j].cap -= f; e[j ^ 1].cap += f; sum += f; flow -= f; if (flow == 0) break; } } if (sum == 0) dep[u] = 0; return sum; }
T dinic(int s, int t){ T F = 0; while (bfs(s, t)) { cur.assign(n, 0); F += dfs(s, t, std::numeric_limits<T>::max()); } return F; }
vector<int> minCut(){ vector<int> c(n); for (int i = 0; i < n; i++) { c[i] = (dep[i] == -1) ? 0 : 1; } return c; }
voidadd(int u, int v, T c){ g[u].push_back(int(e.size())); e.emplace_back(v, c); g[v].push_back(int(e.size())); e.emplace_back(u, 0); } }; intmain(){ ios::sync_with_stdio(false); cin.tie(nullptr);
int n, m, s, t; cin >> n >> m >> s >> t;
MaxFlow<i64> mf(n + 1); for (int i = 1; i <= m; i++) { int u, v; i64 w; cin >> u >> v >> w; mf.add(u, v, w); }
i64 k = mf.dinic(s, t); vector<int> p = mf.minCut(); cerr << k << '\n'; i64 cut = 0; for (int i = 0; i < n; i++) { if (p[i]) { for (auto j : mf.g[p[i]]) { auto [v, w] = mf.e[j]; if (!p[v]) { cut += w; } } } } cout << k << ' ' << cut << '\n'; return0; }