最高标号预留推进算法(HLPP)
template <class Cap> struct HLPP {
struct Edge {
int v, rev;
Cap cap;
Edge(int _v, Cap c, int _rev): v(_v), rev(_rev), cap(c) {}
};
vector<Cap> exflow;
vector<int> h;
vector<int> cnt;
int ht, n, s, t, labelcnt;
vector<vector<Edge> > G;
vector<vector<int> > hq;
void init(int n) {
this->n = n;
ht = labelcnt = 0;
G.resize(n + 1);
for (int i = 0; i <= n; ++i) G[i].clear();
}
void AddEdge(int from, int to, Cap cap) {
G[from].emplace_back(to, cap, G[to].size());
G[to].emplace_back(from, 0, G[from].size() - 1);
}
void Update(int u, int newh) {
++labelcnt;
if (h[u] != n + 1) --cnt[h[u]];
h[u] = newh;
if (newh == n + 1) return;
++cnt[ht = newh];
if (exflow[u] > 0) hq[newh].push_back(u);
}
void GlobalRelabel() {
queue<int> Q;
hq.assign(n + 2, vector<int>(0));
h.assign(n + 1, n + 1);
cnt.assign(n + 1, 0);
Q.push(t);
labelcnt = ht = h[t] = 0;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (Edge& e : G[u]) {
if (h[e.v] == n + 1 && G[e.v][e.rev].cap) {
Update(e.v, h[u] + 1);
Q.push(e.v);
}
}
ht = h[u];
}
}
void Push(int u, Edge& e) {
if (exflow[e.v] == 0) hq[h[e.v]].push_back(e.v);
Cap df = min(exflow[u], e.cap);
e.cap -= df;
G[e.v][e.rev].cap += df;
exflow[u] -= df;
exflow[e.v] += df;
}
void Discharge(int u) {
int nxth = n + 1;
for (Edge& e : G[u]) {
if (e.cap) {
if (h[u] == h[e.v] + 1) {
Push(u, e);
if (exflow[u] <= 0) return;
} else nxth = min(nxth, h[e.v] + 1);
}
}
if (cnt[h[u]] > 1) Update(u, nxth);
else {
for (; ht >= h[u]; hq[ht--].clear()) {
for (int& j : hq[ht]) Update(j, n + 1);
}
}
}
Cap MaxFlow(int s, int t) {
this->s = s;
this->t = t;
exflow.assign(n + 1, 0);
Cap INF = numeric_limits<Cap>::max();
exflow[s] = INF;
exflow[t] = -INF;
GlobalRelabel();
for (Edge& e : G[s]) Push(s, e);
for (; ht >= 0; --ht) {
while (!hq[ht].empty()) {
int u = hq[ht].back();
hq[ht].pop_back();
Discharge(u);
if (labelcnt > (n << 2)) GlobalRelabel();
}
}
return exflow[t] + INF;
}
};
Dinic 算法
template <class Cap> struct Dinic {
struct Edge {
int from, to;
Cap cap, flow;
Edge(int u, int v, Cap c, Cap f): from(u), to(v), cap(c), flow(f) {}
};
int n, m, s, t;
vector<Edge> edges;
vector<vector<int> > G;
vector<bool> vis;
vector<int> d;
vector<int> cur;
void init(int n) {
this->n = n;
G.assign(n + 1, vector<int>(0));
edges.clear();
}
void AddEdge(int from, int to, Cap cap) {
edges.emplace_back(from, to, cap, 0);
edges.emplace_back(to, from, 0, 0);
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS() {
vis.assign(n + 1, 0);
d.assign(n + 1, 0);
queue<int> Q;
Q.push(s);
d[s] = 0;
vis[s] = 1;
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = 0; i < G[x].size(); ++i) {
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
Cap DFS(int x, Cap a) {
if (x == t || a == 0) return a;
Cap flow = 0, f;
for (int& i = cur[x]; i < G[x].size(); ++i) {
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
Cap MaxFlow(int s, int t) {
this->s = s;
this->t = t;
Cap flow = 0;
Cap INF = numeric_limits<Cap>::max();
while (BFS()) {
cur.assign(n + 1, 0);
flow += DFS(s, INF);
}
return flow;
}
};
ISAP 算法(Improved Shortest Augmenting Path)
template <class Cap> struct ISAP {
struct Edge {
int from, to;
Cap cap, flow;
Edge(int u, int v, Cap c, Cap f): from(u), to(v), cap(c), flow(f) {}
};
int n, m, s, t;
vector<Edge> edges;
vector<vector<int> > G;
vector<bool> vis;
vector<int> d;
vector<int> cur;
vector<int> p;
vector<int> num;
void init(int n) {
this->n = n + 1;
G.assign(n + 1, vector<int>(0));
edges.clear();
}
void AddEdge(int from, int to, Cap cap) {
edges.emplace_back(from, to, cap, 0);
edges.emplace_back(to, from, 0, 0);
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS() {
vis.assign(n + 1, 0);
d.assign(n + 1, 0);
queue<int> Q;
Q.push(t);
vis[t] = 1;
d[t] = 0;
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = 0; i < G[x].size(); ++i) {
Edge &e = edges[G[x][i] ^ 1];
if (!vis[e.from] && e.cap > e.flow) {
vis[e.from] = 1;
d[e.from] = d[x] + 1;
Q.push(e.from);
}
}
}
return vis[s];
}
Cap Augment() {
int x = t;
Cap a = numeric_limits<Cap>::max();
while (x != s) {
Edge &e = edges[p[x]];
a = min(a, e.cap - e.flow);
x = edges[p[x]].from;
}
x = t;
while (x != s) {
edges[p[x]].flow += a;
edges[p[x] ^ 1].flow -= a;
x = edges[p[x]].from;
}
return a;
}
Cap MaxFlow(int s, int t) {
this->s = s;
this->t = t;
p.assign(n + 1, 0);
Cap flow = 0;
BFS();
num.assign(n + 1, 0);
for (int i = 0; i < n; ++i) num[d[i]]++;
int x = s;
cur.assign(n + 1, 0);
while (d[s] <= n - 1) {
if (x == t) {
flow += Augment();
x = s;
}
int ok = 0;
for (int i = cur[x]; i < G[x].size(); ++i) {
Edge &e = edges[G[x][i]];
if (e.cap > e.flow && d[x] == d[e.to] + 1) {
ok = 1;
p[e.to] = G[x][i];
cur[x] = i;
x = e.to;
break;
}
}
if (!ok) {
int M = n - 1;
for (int i = 0; i < G[x].size(); ++i) {
Edge &e = edges[G[x][i]];
if (e.cap > e.flow) M = min(M, d[e.to]);
}
if (--num[d[x]] == 0) break;
num[d[x] = M + 1]++;
cur[x] = 0;
if (x != s) x = edges[p[x]].from;
}
}
return flow;
}
};
Edmons-Karp 算法
template <class Cap> struct EdmonsKarp {
struct Edge {
int from, to;
Cap cap, flow;
Edge(int u, int v, Cap c, Cap f): from(u), to(v), cap(c), flow(f) {}
};
int n, m, s, t;
vector<Edge> edges;
vector<vector<int> > G;
vector<Cap> a;
vector<int> p;
void init(int n) {
this->n = n;
G.assign(n + 1, vector<int>(0));
edges.clear();
}
void AddEdge(int from, int to, Cap cap) {
edges.emplace_back(from, to, cap, 0);
edges.emplace_back(to, from, 0, 0);
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS() {
queue<int> Q;
a.assign(n + 1, 0);
Q.push(s);
a[s] = numeric_limits<Cap>::max();
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (int i = 0; i < G[x].size(); ++i) {
Edge& e = edges[G[x][i]];
if (!a[e.to] && e.cap > e.flow) {
p[e.to] = G[x][i];
a[e.to] = min(a[x], e.cap - e.flow);
Q.push(e.to);
}
}
if (a[t]) return true;
}
return false;
}
Cap MaxFlow(int s, int t) {
this->s = s;
this->t = t;
p.assign(n + 1, 0);
Cap flow = 0;
while (BFS()) {
for (int u = t; u != s; u = edges[p[u]].from) {
edges[p[u]].flow += a[t];
edges[p[u] ^ 1].flow -= a[t];
}
flow += a[t];
}
return flow;
}
};