Description
给定一张 n n n 点 m m m 边的有向图,求 1 → n 1 \to n 1→n 的最小割的容量和边数。
Analysis
第一问是模板,直接套最小割(最大流)即可。
第二问的话,我们可以将流满的边容量改成
1
1
1,没流满的改成
∞
\infty
∞,在新图上跑一遍最小割即可求出。
Code
最大流贴的是 jiangly 的模板
// Problem: P1344 [USACO4.4] 追查坏牛奶 Pollutant Control
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1344
// Memory Limit: 128 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;
template<class T>
bool chmax(T &a, const T &b){
if(a < b){ a = b; return true; }
return false;
}
template<class T>
bool chmin(T &a, const T &b){
if(a > b){ a = b; return true; }
return false;
}
const int INF = 2e9;
template<class T>
struct MaxFlow {
struct _Edge {
int to;
T cap;
_Edge(int to, T cap) : to(to), cap(cap) {}
};
int n;
T inf;
std::vector<_Edge> e;
std::vector<std::vector<int>> g;
std::vector<int> cur, h;
MaxFlow() {}
MaxFlow(int n) {
init(n);
inf = numeric_limits<T>::max();
}
void init(int n) {
this->n = n;
e.clear();
g.assign(n, {});
cur.resize(n);
h.resize(n);
}
bool bfs(int s, int t) {
h.assign(n, -1);
std::queue<int> que;
h[s] = 0;
que.push(s);
while (!que.empty()) {
const int u = que.front();
que.pop();
for (int i : g[u]) {
int v = e[i].to;
T c = e[i].cap;
if (c > 0 && h[v] == -1) {
h[v] = h[u] + 1;
if (v == t) {
return true;
}
que.push(v);
}
}
}
return false;
}
T dfs(int u, int t, T f) {
if (u == t) {
return f;
}
auto r = f;
for (int &i = cur[u]; i < int(g[u].size()); ++i) {
const int j = g[u][i];
int v = e[j].to;
T c = e[j].cap;
if (c > 0 && h[v] == h[u] + 1) {
auto a = dfs(v, t, std::min(r, c));
e[j].cap -= a;
e[j ^ 1].cap += a;
r -= a;
if (r == 0) {
return f;
}
}
}
return f - r;
}
void addEdge(int u, int v, T c) {
g[u].push_back(e.size());
e.emplace_back(v, c);
g[v].push_back(e.size());
e.emplace_back(u, 0);
}
T flow(int s, int t) {
T ans = 0;
while (bfs(s, t)) {
cur.assign(n, 0);
ans += dfs(s, t, std::numeric_limits<T>::max());
}
return ans;
}
std::vector<bool> minCut() {
std::vector<bool> c(n);
for (int i = 0; i < n; i++) {
c[i] = (h[i] != -1);
}
return c;
}
struct Edge {
int from;
int to;
T cap;
T flow;
};
std::vector<Edge> edges() {
std::vector<Edge> a;
for (int i = 0; i < e.size(); i += 2) {
Edge x;
x.from = e[i + 1].to;
x.to = e[i].to;
x.cap = e[i].cap + e[i + 1].cap;
x.flow = e[i + 1].cap;
a.push_back(x);
}
return a;
}
};
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
// Find the capacity of the mincut.
MaxFlow<int> G(n);
for(int i = 0, u, v, w; i < m; i++){
cin >> u >> v >> w;
u--, v--;
G.addEdge(u, v, w);
}
int ans = G.flow(0, n - 1);
// Find the number of edges of the mincut.
auto edges = G.edges();
// Build a new network graph.
MaxFlow<int> G2(n);
for(auto &edge: edges){
if(edge.cap == edge.flow) G2.addEdge(edge.from, edge.to, 1);
else G2.addEdge(edge.from, edge.to, INF);
}
int ecnt = G2.flow(0, n - 1);
cout << ans << ' ' << ecnt << endl;
return 0;
}