22527 鄭竣陽
Brine
BrineTW#7355
Index
Glossary
Maximum Flow
Max-Flow Min-Cut
Max Flow Algorithm
typedef long long ll;
struct FordFulkerson {
int s, t, V;
vector< vector<int> > graph;
vector< vector<ll> > cap;
vector<bool> visited;
FordFulkerson(int V): V(V), graph(V), visited(V) {
cap.resize(V, vector<ll>(V));
}
void addEdge(int u, int v, int w) {
graph[u].push_back(v);
graph[v].push_back(u);
cap[u][v] += w;
}
ll dfs(int u, ll f = INT64_MAX) {
if (u == t) return f;
visited[u] = 1;
for (auto& v: graph[u]) {
if (cap[u][v] == 0 || visited[v]) continue;
ll fv = dfs(v, min(f, cap[u][v]));
if (fv) {
cap[u][v] -= fv;
cap[v][u] += fv;
return fv;
}
}
return 0;
}
ll maximumFlow(int s, int t) {
this->s = s, this->t = t;
ll f = 0;
for (ll augFlow; augFlow = dfs(s); f += augFlow) {
visited.assign(V, 0);
}
return f;
}
};
typedef long long ll;
struct EdmondsKarp {
int V;
vector< vector<ll> > cap;
vector< vector<int> > graph;
vector<int> p;
EdmondsKarp(int V): V(V), graph(V), p(V) {
cap.resize(V, vector<ll>(V));
}
void addEdge(int u, int v, int w) {
graph[u].push_back(v);
graph[v].push_back(u);
cap[u][v] += w;
}
bool bfs(int s, int t) {
p.assign(V, 0);
queue<int> q;
q.push(s);
while (q.size()) {
auto u = q.front();
q.pop();
for (auto& v: graph[u]) {
if (p[v] || !cap[u][v]) continue;
p[v] = u;
if (v == t) return 1;
q.push(v);
}
}
return 0;
}
ll maximumFlow(int s, int t) {
ll f = 0;
while (bfs(s, t)) {
ll augFlow = INT64_MAX;
for (int u = t; u != s; u = p[u]) {
augFlow = min(augFlow, cap[p[u]][u]);
}
for (int u = t; u != s; u = p[u]) {
cap[p[u]][u] -= augFlow;
cap[u][p[u]] += augFlow;
}
f += augFlow;
}
return f;
}
};
Dinitz
typedef long long ll;
struct Dinitz {
int s, t, V;
vector< vector<int> > graph;
vector< vector<ll> > cap;
vector<int> level, toCheck;
Dinitz(int V): V(V), graph(V), level(V), toCheck(V) {
cap.resize(V, vector<ll>(V));
}
void addEdge(int u, int v, int w) {
graph[u].push_back(v);
graph[v].push_back(u);
cap[u][v] += w;
}
int bfs() {
level.assign(V, 0);
level[s] = 1;
queue<int> q;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
for (auto& v: graph[u]) {
if (level[v] || !cap[u][v]) continue;
level[v] = level[u] + 1;
q.push(v);
}
}
return level[t];
}
ll dfs(int u, ll f = INT64_MAX) {
if (u == t) return f;
for (auto& i = toCheck[u]; i < graph[u].size(); i++) {
auto& v = graph[u][i];
if (!cap[u][v] || level[v] != level[u] + 1) continue;
ll fv = dfs(v, min(f, cap[u][v]));
if (fv) {
cap[u][v] -= fv;
cap[v][u] += fv;
return fv;
}
}
return 0;
}
ll maximumFlow(int s, int t) {
this->s = s, this->t = t;
ll f = 0, augFlow;
while (bfs()) {
fill(toCheck.begin(), toCheck.end(), 0);
while (augFlow = dfs(s)) f += augFlow;
}
return f;
}
};
Push Relabel
typedef long long ll;
struct PushRelabel {
int V, i;
vector<vector<int>> graph, Q;
vector<vector<ll>> cap;
vector<int> h;
vector<ll> excess;
vector<bool> active;
PushRelabel(int V): V(V), graph(V), Q(V << 1 ^ 1), h(V), excess(V), active(V) {
cap.resize(V, vector<ll>(V));
}
void addEdge(int u, int v, int w) {
graph[u].push_back(v);
graph[v].push_back(u);
cap[u][v] += w;
}
void enqueue(int u) {
if (!active[u] && excess[u]) {
active[u] = 1;
Q[h[u]].push_back(u);
i = max(i, h[u]);
}
}
void push(int u, int v) {
ll f = min(excess[u], cap[u][v]);
if (h[u] > h[v] && f) {
cap[u][v] -= f;
cap[v][u] += f;
excess[v] += f;
excess[u] -= f;
enqueue(v);
}
}
void relabel(int u) {
h[u] = V * 2 + 1;
for (auto& v: graph[u]) if (cap[u][v]) {
h[u] = min(h[u], h[v] + 1);
}
enqueue(u);
}
void discharge(int u) {
for (auto& v: graph[u]) {
if (!excess[u]) break;
push(u, v);
}
if (excess[u]) relabel(u);
}
ll maximumFlow(int s, int t) {
excess[s] = INT64_MAX;
h[s] = V;
active[s] = active[t] = 1;
for (auto& v: graph[s]) push(s, v);
for (i = 0; i >= 0; i--) {
while (Q[i].size()) {
int u = Q[i].back();
Q[i].pop_back();
active[u] = 0;
discharge(u);
}
}
return excess[t];
}
};
struct PushRelabel {
int V, i;
vector<vector<int>> graph, Q;
vector<vector<ll>> cap;
vector<ll> excess;
vector<int> h, count;
vector<bool> active;
PushRelabel(int V): V(V), graph(V), Q(V), h(V), excess(V), count(V + 1), active(V) {
cap.resize(V, vector<ll>(V));
}
void addEdge(int u, int v, int w) {
graph[u].push_back(v);
graph[v].push_back(u);
cap[u][v] += w;
}
void enqueue(int u) {
if (!active[u] && excess[u] && h[u] < V) {
active[u] = 1;
Q[h[u]].push_back(u);
i = max(i, h[u]);
}
}
void push(int u, int v) {
ll f = min(excess[u], cap[u][v]);
if (h[u] == h[v] + 1 && f) {
cap[u][v] -= f;
cap[v][u] += f;
excess[v] += f;
excess[u] -= f;
enqueue(v);
}
}
void gap(int k) {
for (int u = 0; u < V; u++) if (h[u] >= k) {
count[h[u]]--;
h[u] = max(h[u], V);
count[h[u]]++;
enqueue(u);
}
}
void relabel(int u) {
count[h[u]]--;
h[u] = V;
for (auto& v: graph[u]) if (cap[u][v]) {
h[u] = min(h[u], h[v] + 1);
}
count[h[u]]++;
enqueue(u);
}
void discharge(int u) {
for (auto& v: graph[u]) {
if (!excess[u]) break;
push(u, v);
}
if (excess[u]) (count[h[u]] == 1) ? gap(h[u]) : relabel(u);
}
ll maximumFlow(int s, int t) {
excess[s] = INT64_MAX;
count[0] = V;
enqueue(s);
active[t] = 1;
for (i = 0; i >= 0; i--) {
while (Q[i].size()) {
int u = Q[i].back();
Q[i].pop_back();
active[u] = 0;
discharge(u);
}
}
return excess[t];
}
};
聽說,每次有人在建國中學資訊讀書會遇到看不懂的圖論概念的時候,就會有一位不知名先生出現,在你最絕望的時候從你背後輕拍你的肩膀,當你在想「到底是誰設計出這個演算法的啦幹」的時候,他就會到你的耳邊輕輕跟你說:
聽說,每次有人在建國中學資訊讀書會遇到看不懂的圖論概念的時候,就會有一位不知名先生出現,在你最絕望的時候從你背後輕拍你的肩膀,當你在想「到底是誰設計出這個演算法的啦幹」的時候,他就會到你的耳邊輕輕跟你說:
「哈哈,是我啦」
聽說,每次有人在建國中學資訊讀書會遇到看不懂的圖論概念的時候,就會有一位不知名先生出現,在你最絕望的時候從你背後輕拍你的肩膀,當你在想「到底是誰設計出這個演算法的啦幹」的時候,他就會到你的耳邊輕輕跟你說:
「哈哈,是我啦」
Solutions
struct Dinitz {
struct Edge {
int v, c, r;
Edge(int v, int c, int r): v(v), c(c), r(r) {}
};
int s, t, V;
vector< vector<Edge> > graph;
vector<int> level, toCheck;
Dinitz(int V): V(V), graph(V), level(V), toCheck(V) {}
void addEdge(int u, int v, int w) {
graph[u].push_back({v, w, graph[v].size()});
graph[v].push_back({u, 0, graph[u].size() - 1});
}
int bfs() {
level.assign(V, 0);
level[s] = 1;
queue<int> q;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
for (auto& [v, c, r]: graph[u]) {
if (level[v] || !c) continue;
level[v] = level[u] + 1;
q.push(v);
}
}
return level[t];
}
int dfs(int u, int f = INT32_MAX) {
if (u == t) return f;
for (auto& i = toCheck[u]; i < graph[u].size(); i++) {
auto& [v, c, r] = graph[u][i];
if (!c || level[v] != level[u] + 1) continue;
int fv = dfs(v, min(f, c));
if (fv) {
c -= fv;
graph[v][r].c += fv;
return fv;
}
}
return 0;
}
ll maximumFlow(int s, int t) {
this->s = s, this->t = t;
ll f = 0, augFlow;
while (bfs()) {
fill(toCheck.begin(), toCheck.end(), 0);
while (augFlow = dfs(s)) f += augFlow;
}
return f;
}
};
Min Cost Flow
typedef long long ll;
struct SuccessiveSP {
struct Edge {
int v, c, w, r;
Edge(int v, int c, int w, int r): v(v), c(c), w(w), r(r) {}
};
int V;
vector< vector<Edge> > graph;
vector<ll> d;
vector<int> p, edgeId;
vector<bool> visited, inQueue;
SuccessiveSP(int V): V(V), graph(V) {}
void addEdge(int u, int v, int c, int w) {
graph[u].emplace_back(v, c, w, graph[v].size());
graph[v].emplace_back(u, 0, -w, graph[u].size() - 1);
}
void reset() {
d.assign(V, INT64_MAX);
p.assign(V, 0);
edgeId.assign(V, 0);
visited.assign(V, 0);
inQueue.assign(V, 0);
}
pair<ll, ll> SPFA(int s, int t) {
reset();
d[s] = 0;
queue<int> q;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
inQueue[u] = 0;
for (int i = 0; i < graph[u].size(); i++) {
auto& [v, c, w, r] = graph[u][i];
if (c && d[u] + w < d[v]) {
p[v] = u;
edgeId[v] = i;
d[v] = d[u] + w;
if (inQueue[v]) continue;
inQueue[v] = 1;
q.push(v);
}
}
}
if (d[t] == INT64_MAX) return {0, 0};
int f = INT32_MAX;
for (int u = t; u != s; u = p[u]) {
f = min(f, graph[p[u]][edgeId[u]].c);
}
for (int u = t; u != s; u = p[u]) {
graph[p[u]][edgeId[u]].c -= f;
graph[u][graph[p[u]][edgeId[u]].r].c += f;
}
return {f, d[t]};
}
};
Templates
typedef long long ll;
struct Dinitz {
struct Edge {
int v, c, r;
Edge(int v, int c, int r): v(v), c(c), r(r) {}
};
int s, t, V;
vector< vector<Edge> > graph;
vector<int> level, toCheck;
Dinitz(int V): V(V), graph(V), level(V), toCheck(V) {}
void addEdge(int u, int v, int w) {
graph[u].push_back({v, w, graph[v].size()});
graph[v].push_back({u, 0, graph[u].size() - 1});
}
int bfs() {
level.assign(V, 0);
level[s] = 1;
queue<int> q;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
for (auto& [v, c, r]: graph[u]) {
if (level[v] || !c) continue;
level[v] = level[u] + 1;
q.push(v);
}
}
return level[t];
}
int dfs(int u, int f = INT32_MAX) {
if (u == t) return f;
for (auto& i = toCheck[u]; i < graph[u].size(); i++) {
auto& [v, c, r] = graph[u][i];
if (!c || level[v] != level[u] + 1) continue;
int fv = dfs(v, min(f, c));
if (fv) {
c -= fv;
graph[v][r].c += fv;
return fv;
}
}
return 0;
}
ll maximumFlow(int s, int t) {
this->s = s, this->t = t;
ll f = 0, augFlow;
while (bfs()) {
fill(toCheck.begin(), toCheck.end(), 0);
while (augFlow = dfs(s)) f += augFlow;
}
return f;
}
};
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct PushRelabel {
struct Edge {
int v, c, r;
Edge(int v, int c, int r): v(v), c(c), r(r) {}
};
int V, i;
vector< vector<Edge> > graph;
vector< vector<int> > Q;
vector<int> h;
vector<ll> excess;
vector<bool> active;
PushRelabel(int V): V(V), graph(V), Q(V << 1 ^ 1), h(V), excess(V), active(V) {}
void addEdge(int u, int v, int w) {
graph[u].push_back({v, w, graph[v].size()});
graph[v].push_back({u, 0, graph[u].size()});
}
void enqueue(int u) {
if (!active[u] && excess[u]) {
active[u] = 1;
Q[h[u]].push_back(u);
i = max(i, h[u]);
}
}
void push(int u, Edge& e) {
auto& [v, c, r] = e;
int f = min(int(excess[u]), c);
if (h[u] > h[v] && f) {
c -= f;
graph[v][r].c += f;
excess[v] += f;
excess[u] -= f;
enqueue(v);
}
}
void relabel(int u) {
h[u] = V * 2 + 1;
for (auto& [v, c, r]: graph[u]) if (c) {
h[u] = min(h[u], h[v] + 1);
}
enqueue(u);
}
void discharge(int u) {
for (auto& e: graph[u]) {
if (!excess[u]) break;
push(u, e);
}
if (excess[u]) relabel(u);
}
ll maximumFlow(int s, int t) {
excess[s] = INT64_MAX;
h[s] = V;
active[s] = active[t] = 1;
for (auto& v: graph[s]) push(s, v);
for (i = 0; i >= 0; i--) {
while (Q[i].size()) {
int u = Q[i].back();
Q[i].pop_back();
active[u] = 0;
discharge(u);
}
}
return excess[t];
}
};
int main() {
}
typedef long long ll;
struct SuccessiveSP {
struct Edge {
int v, c, w, r;
Edge(int v, int c, int w, int r): v(v), c(c), w(w), r(r) {}
};
int V;
vector< vector<Edge> > graph;
vector<ll> d;
vector<int> p, edgeId;
vector<bool> visited, inQueue;
SuccessiveSP(int V): V(V), graph(V) {}
void addEdge(int u, int v, int c, int w) {
graph[u].emplace_back(v, c, w, graph[v].size());
graph[v].emplace_back(u, 0, -w, graph[u].size() - 1);
}
void reset() {
d.assign(V, INT64_MAX);
p.assign(V, 0);
edgeId.assign(V, 0);
visited.assign(V, 0);
inQueue.assign(V, 0);
}
pair<ll, ll> SPFA(int s, int t) {
reset();
d[s] = 0;
queue<int> q;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
inQueue[u] = 0;
for (int i = 0; i < graph[u].size(); i++) {
auto& [v, c, w, r] = graph[u][i];
if (c && d[u] + w < d[v]) {
p[v] = u;
edgeId[v] = i;
d[v] = d[u] + w;
if (inQueue[v]) continue;
inQueue[v] = 1;
q.push(v);
}
}
}
if (d[t] == INT64_MAX) return {0, 0};
int f = INT32_MAX;
for (int u = t; u != s; u = p[u]) {
f = min(f, graph[p[u]][edgeId[u]].c);
}
for (int u = t; u != s; u = p[u]) {
graph[p[u]][edgeId[u]].c -= f;
graph[u][graph[p[u]][edgeId[u]].r].c += f;
}
return {f, d[t]};
}
};
啪!沒了