网络流的一些定义
- 网络为一个有向图,其中每一条边
(
x
,
y
)
∈
E
(x,y)\in E
(x,y)∈E都有一个权值
c
(
x
,
y
)
c(x,y)
c(x,y),若
(
x
,
y
)
∉
E
(x,y) \not \in E
(x,y)∈E则
c
(
x
,
y
)
=
0
c(x,y)=0
c(x,y)=0.
且有两个点 S , T S,T S,T称为源点和汇点。 - 定义
f
(
x
,
y
)
f(x,y)
f(x,y)为该网络的流量函数,那么
f
(
x
,
y
)
f(x,y)
f(x,y)有以下性质:
1. f ( x , y ) ≤ c ( x , y ) f(x,y) \leq c(x,y) f(x,y)≤c(x,y)
2. f ( x , y ) = − f ( y , x ) f(x,y)=-f(y,x) f(x,y)=−f(y,x)
3. ∀ x ≠ S , x ≠ T , ∑ ( u , x ) ∈ E f ( u , x ) = ∑ ( x , v ) ∈ E f ( x , v ) \forall x \not = S, x \not = T, \sum_{(u,x)\in E }f(u,x)=\sum_{(x,v)\in E}f(x,v) ∀x=S,x=T,∑(u,x)∈Ef(u,x)=∑(x,v)∈Ef(x,v) - 以上三条性质被称为容量限制,斜对称,容量守恒
- 定义一条边的剩余容量为 c ( x , y ) − f ( x , y ) c(x,y)-f(x,y) c(x,y)−f(x,y)
最大流
对于一张网络,是的 ∑ ( S , v ) ∈ E f ( S , v ) \sum_{(S,v) \in E}f(S,v) ∑(S,v)∈Ef(S,v)最大的流函数称为该函数的最大流
E-K增广路算法
若一条从源点 S S S到汇点 T T T的路径的剩余容量都大于 0 0 0,则称这条路径为一条增广路。
那么E-K算法的实质是不断找剩余容量最大的增广路,然后更新路径容量(大概就是这样qwq
code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 100;
const int M = 1e5 + 100;
const int INF = 0x3f3f3f3f;
template <typename T> inline void read(T &s) {
s = 0; T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, m, s, t, tot = 1, maxflow = 0;
int lin[N], pre[N], incf[N];
bool vis[N];
struct edge {
int next, to, dis;
}e[M<<1];
inline void add(int from, int to, int dis) {
e[++tot].to = to; e[tot].next = lin[from]; e[tot].dis = dis; lin[from] = tot;
e[++tot].to = from; e[tot].next = lin[to]; e[tot].dis = 0; lin[to] = tot;
}
bool bfs() {
memset(vis, false, sizeof(vis));
queue<int> q; q.push(s); vis[s] = 1;
incf[s] = INF;
while (q.size()) {
int x = q.front(); q.pop();
for (int i = lin[x]; i; i = e[i].next) {
if (e[i].dis) {
int y = e[i].to;
if (vis[y]) continue;
incf[y] = min(incf[x], e[i].dis);
pre[y] = i;
q.push(y); vis[y] = true;
if (y == t) return true;
}
}
}
return false;
}
void update() {
int x = t;
while (x != s) {
int i = pre[x];
e[i].dis -= incf[t];
e[i ^ 1].dis += incf[t];
x = e[i ^ 1].to;
}
maxflow += incf[t];
}
int main() {
read(n), read(m), read(s), read(t);
int u, v, w;
for (int i = 1; i <= m; ++i) {
read(u), read(v), read(w);
add(u, v, w);
}
while (bfs()) update();
printf("%d\n", maxflow);
return 0;
}