Note -「網路流相關板子」
阿新 • • 發佈:2022-01-06
EK.
很少用到,知道思想即可。
懶得寫封裝的屑。
queue<int> q; int Cap[MAXN][MAXN], Flow[MAXN][MAXN], Aug[MAXN], fa[MAXN], n; void Add_Cap(int u, int v, int C) { Cap[u][v] += C; } int bfs(int s, int t) { for(int i = 1; i <= n; i++) { Aug[i] = 0; fa[i] = 0; } while(!q.empty()) q.pop(); Aug[s] = INF; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); for(int v = 1; v <= n; v++) if(Cap[u][v] - Flow[u][v] > 0 && !Aug[v]) { Aug[v] = Min(Aug[u], Cap[u][v] - Flow[u][v]); fa[v] = u; if(v == t) return Aug[v]; q.push(v); } } return 0; } int EK(int s, int t) { int Delta = bfs(s, t), res = 0, u; while(Delta) { res += Delta; for(int v = t; v != s; v = u) { u = fa[v]; Flow[u][v] += Delta; Flow[v][u] -= Delta; } Delta = bfs(s, t); } return res; }
Dinic.
時間複雜度玄學的常用最大流板子。
struct Maximum_Flow { #define Type int struct edge { int v, nxt; edge() {} edge(int V, int Nxt) { v = V, nxt = Nxt; } } e[MAXM << 1]; int n, cnt, s, t; Type Cap[MAXM << 1], Flow[MAXM << 1]; int Lab[MAXL], Cur[MAXL], head[MAXL], Col[MAXL]; queue<int> q; void init(int N, int S, int T) { for(int i = 0; i <= cnt; i++) Flow[i] = 0, Cap[i] = 0; n = N, cnt = 0, s = S, t = T; for(int i = 1; i <= n; i++) head[i] = -1, Col[i] = 0; } void Add_Edge(int u, int v, Type w) { Cap[cnt] += w; e[cnt] = edge(v, head[u]); head[u] = cnt++; e[cnt] = edge(u, head[v]); head[v] = cnt++; } bool Lab_Vertex() { for(int i = 1; i <= n; i++) Lab[i] = 0; Lab[t] = 1; while(!q.empty()) q.pop(); q.push(t); while(!q.empty()) { int v = q.front(); q.pop(); for(int i = head[v], u; ~i; i = e[i].nxt) { u = e[i].v; if(!Lab[u] && Cap[i ^ 1] - Flow[i ^ 1]) { Lab[u] = Lab[v] + 1; q.push(u); if(u == s) return Lab[s]; } } } return Lab[s]; } Type Widen(int u, Type Limit) { if(u == t) return Limit; Type Used = 0, Delta; for(int i = Cur[u], v; ~i; i = e[i].nxt) { v = e[i].v; Cur[u] = i; if(Lab[v] + 1 != Lab[u] || Cap[i] - Flow[i] <= 0) continue; Delta = Widen(v, Min(Limit - Used, Cap[i] - Flow[i])); Used += Delta, Flow[i] += Delta, Flow[i ^ 1] -= Delta; if(Used == Limit) return Used; } return Used; } Type Dinic() { Type res = 0; while(Lab_Vertex()) { for(int i = 1; i <= n; i++) Cur[i] = head[i]; res += Widen(s, INF); if(res < 0) return INF; } return res; } void Color(int u) { Col[u] = 1; for(int i = head[u]; ~i; i = e[i].nxt) if(Cap[i] - Flow[i] > 0 && !Col[e[i].v]) Color(e[i].v); } #undef Type } Flow_Graph;
spfa + Dinic.
普通最小費用最大流。(小心被卡?
struct Minimum_Cost_Maximum_Flow { #define Type int struct edge { int v, nxt; Type Wei, Cap, Flow; edge() {} edge(int V, int Nxt, Type C, Type W, Type F) { v = V, nxt = Nxt, Cap = C, Wei = W, Flow = F; } } e[MAXM << 1]; int head[MAXM << 1], cnt = 0; void Add_Edge(int u, int v, Type c, Type w) { e[cnt] = edge(v, head[u], c, w, 0); head[u] = cnt++; e[cnt] = edge(u, head[v], 0, -w, 0); head[v] = cnt++; } int Cur[MAXN], n, s, t; bool vis[MAXN], Flag[MAXN]; Type Dist[MAXN], Aug[MAXN], Flow, Cost; void init(int N, int S, int T) { n = N, s = S, t = T, cnt = 0; for(int i = 1; i <= n; i++) head[i] = -1; } bool spfa() { for(int i = 1; i <= n; i++) Dist[i] = INF, vis[i] = false, Aug[i] = INF; Dist[s] = 0, vis[s] = true, Aug[s] = INF; queue<int> q; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i = head[u], v; ~i; i = e[i].nxt) { v = e[i].v; if(e[i].Cap - e[i].Flow > 0 && Dist[v] > Dist[u] + e[i].Wei) { Dist[v] = Dist[u] + e[i].Wei; Aug[v] = Min(Aug[u], e[i].Cap - e[i].Flow); if(!vis[v]) vis[v] = true, q.push(v); } } } return Dist[t] != INF; } Type Widen(int u, Type Limit) { if(u == t) return Limit; Flag[u] = true; Type Used = 0, Delta; for(int i = Cur[u], v; ~i; i = e[i].nxt) { v = e[i].v; if(Flag[v] || Dist[u] + e[i].Wei != Dist[v] || e[i].Cap - e[i].Flow <= 0) continue; Cur[u] = i; Delta = Widen(v, Min(Limit - Used, e[i].Cap - e[i].Flow)); Used += Delta, e[i].Flow += Delta, e[i ^ 1].Flow -= Delta; if(Used == Limit) break; } Flag[u] = false; return Used; } void Dinic() { Flow = 0, Cost = 0; Type Delta; while(spfa()) { for(int i = 1; i <= n; i++) Cur[i] = head[i]; Delta = Widen(s, INF); Flow += Delta, Cost += Delta * Dist[t]; } } #undef Type } Flow_Graph;
spfa + Dijkstra + EK
時間複雜度穩定,不會被卡。呃不會被卡吧。
struct Minimum_Cost_Maximum_Flow {
#define Type int
struct edge {
int v, nxt;
Type Wei, Cap, Flow;
edge() {}
edge(int V, int Nxt, Type C, Type W, Type F) {
v = V, nxt = Nxt, Cap = C, Wei = W, Flow = F;
}
} e[MAXM << 1];
int head[MAXM << 1], cnt = 0;
void Add_Edge(int u, int v, Type c, Type w) {
e[cnt] = edge(v, head[u], c, w, 0);
head[u] = cnt++;
e[cnt] = edge(u, head[v], 0, -w, 0);
head[v] = cnt++;
}
struct node {
int x;
Type dis;
node() {}
node(int X, Type Dis) {
x = X, dis = Dis;
}
friend bool operator < (node One, node TheOther) {
return One.dis > TheOther.dis;
}
};
struct Back {
int Pre, id;
Back() {}
Back(int P, int Id) {
Pre = P, id = Id;
}
} Last[MAXN];
int Cur[MAXN], n, s, t;
bool vis[MAXN], Flag[MAXN];
Type Dist[MAXN], Aug[MAXN], h[MAXN], Flow, Cost;
void init(int N, int S, int T) {
n = N, s = S, t = T, cnt = 0;
for(int i = 1; i <= n; i++)
head[i] = -1;
}
void spfa(int s, int t) {
for(int i = 1; i <= n; i++)
h[i] = INF, vis[i] = false;
h[s] = 0, vis[s] = true;
queue<int> q;
q.push(s);
while(!q.empty()) {
int u = q.front(); q.pop();
vis[u] = false;
for(int i = head[u], v; ~i; i = e[i].nxt) {
v = e[i].v;
if(e[i].Cap - e[i].Flow > 0 && h[v] > h[u] + e[i].Wei) {
h[v] = h[u] + e[i].Wei;
if(!vis[v])
vis[v] = true, q.push(v);
}
}
}
}
bool Dijkstra(int s, int t) {
for(int i = 1; i <= n; i++)
Dist[i] = INF, Last[i] = Back(-1, -1), vis[i] = false, Aug[i] = INF;
priority_queue<node> q;
Dist[s] = 0;
q.push(node(s, Dist[s]));
while(!q.empty()) {
int u = q.top().x; q.pop();
if(vis[u])
continue;
vis[u] = true;
for(int i = head[u], v; ~i; i = e[i].nxt) {
v = e[i].v;
if(e[i].Cap - e[i].Flow > 0 && Dist[v] > Dist[u] + e[i].Wei + h[u] - h[v]) {
Last[v] = Back(u, i);
Dist[v] = Dist[u] + e[i].Wei + h[u] - h[v];
Aug[v] = Min(Aug[u], e[i].Cap - e[i].Flow);
q.push(node(v, Dist[v]));
}
}
}
return Dist[t] != INF;
}
void EK() {
Flow = 0, Cost = 0;
spfa(s, t);
while(Dijkstra(s, t)) {
Flow += Aug[t];
Cost += Aug[t] * (Dist[t] + h[t]);
int pos = t;
while(pos != s) {
e[Last[pos].id].Flow += Aug[t];
e[Last[pos].id ^ 1].Flow -= Aug[t];
pos = Last[pos].Pre;
}
for(int i = 1; i <= n; i++)
h[i] += Dist[i];
}
}
#undef Type
} Flow_Graph;