网络流 学习笔记

共 1677 字
14 分钟
0 次阅读

流流。

概念

网络流:一个算法。

网络:一张有向图,上面有源点和汇点。(水管线路)

弧:网络上的一条边。下文简称边。(水管)

流量:一条边的一个属性。记作 $f(x,y)$。可以为负。(水管运输水量)

容量:一条边的另一个属性。记作 $c(x,y)$。(水管最大流量)

源点:起点。(水厂)

汇点:终点。(废水回收站?)

容量网络:每条边都有容量的网络。(规划图)

流量网络:每条边都有容量的网络。(计划)

残留容量:对边来说,残留容量 = 容量 - 流量。

残量网络:每条边都有残留容量的网络。(水管冗余)

性质

容量限制

不是人话:$\forall (x,y) \in E,f(x,y) \leq c(x,y)$。

人话:流量不超过容量。

流量守恒

不是人话:$\forall x \in V$ 且 $x \neq S$ 且 $x \neq T$,$\sum_{(u,x) \in E} f(u,x) = \sum_{(x,v) \in E} f(x,v)$。

人话:吃进去多少就吐出来多少。

斜对称

不是人话:$\forall (x,y) \in E,f(y,x) = -f(x,y)$。

人话:正着是多少反着就是负多少。

最大流

概念

网络的流量:在某个流量网络中汇点收到的流量。(回收站收到的水量)

最大流:网络的流量的最大值。(回收站最多能收到的的水量)

最大流网络:使得网络的流量最大的流量网路。(最优计划线路图)

算法

EK 增广路

概念

增广路:一条在残量网络上从 $S$ 到 $T$ 的路径,且路径上所有残留容量均为正。(一条可以抵达的路线)

增广路定理:流量网络达到最大流当且仅当残量网络没有增广路。(都到不了当然无法获得更大流量)

算法

(1) 在残量网络上从 $S$ 点出发跑 bfs,找到边数最小的增广路,并记录各边残留容量的最小值。若找不到增广路,结束。

(2) 更新答案和残量网络。

(3) 回到 (1)。

理解

残量网络的更新需要同时更新正向边 $-F$ 和反向边 $+F$,这是为了给算法一些“反悔”的机会,若流量流经反向边则代表正边撤回一些流量去往新方向。

时间复杂度

每条边被增广的次数是 $O(n)$ 的,总计增广 $O(nm)$ 次,一次 bfs 增广为 $O(m)$,总复杂度 $O(nm^2)$。

实现

由于需要快速寻找反向边,链式前向星一般来说比邻接表更好用。

但是!作为 vector 神教的一员,我们不能扔下邻接表不管!

嘿嘿那我退出 vector 神教了。

我们在每条边直接记录反向边的编号即可做到 $O(1)$ 查询。代价是空间常数有点大。

真的不是我的链前写不好,你一定要相信我!

Dinic

算法

(1) bfs 跑出分层图。

(2) 根据层次进行多次 dfs 遍历残量网络,一次找到一条增广路并进行更新。

优化

多路增广

一次 bfs 可以找到 $1 \sim m$ 条增广路,但 dfs 的更新没有优化,导致复杂度还是很爆。

我们在 dfs 的时候对于每个点 $x$,记录 $x \rightarrow T$ 的路径上已经用掉的流量,如果已经达到上限就不再遍历搜索其他边,直接返回已用去的流量。

到达汇点时,则返回收到的流量并进行更新。

当前弧

在一个分层图中,已经处理结束的边就没用了,因为我们是依次遍历每个出发点,所以可以记录上一次推到哪里,继续向后。

时间复杂度

也就 $O(n^2m)$。但是常数超级小,甚至能通过 $10^5$。

ISAP & HLPP

Dinic 已经很快了,拿更多的码量去换不太明显的效率提升实在有点亏。所以, 我不学!

最小割

概念

割集:一个源点为 $S$,汇点为 $T$ 的网络划分为两个点集 $s$ 和 $t$,且 $S \in s,T \in t$,于是所有边 $(x,y)$ 满足 $x \in s,y \in t$ 构成的集合成为割集。(切割后网络不连通)

最小割:容量和最小的割集。

求法

根据最大流最小割定理,原图最大流即等于最小割。

Ohh 这么奇幻。

费用流

概念

单位流量费用:单位费用。一条边的费用 $=$ 流量 $\times$ 单位费用。记作 $w(x,y)$。

最小费用最大流:在所有最大流网络中,费用最小的。(不应该叫最大流最小费用吗)

算法

SSP

其实是上面两个算法的变种。

我们复制 EK 的内容并稍作修改:

(1) 在残量网络上从 $S$ 点出发跑 bfs SPFA,找到 边数 单位费用和最小的增广路,并记录各边残留容量的最小值。若找不到增广路,结束。

(2) 更新答案和残量网络。

(3) 回到 (1)。

就好了。

实现

注意反向边的单位费用是 $-w(x,y)$。

但是吧,

关于SPFA

  • 它死了

万一良心出题人卡你怎么办。

不知道你是否听过 Johnson 全源最短路。这个算法通过一次 SPFA 重新标注边权使得 Dijkstra 可以运行。

我们可以利用类似的 Primal-Dual 原始对偶算法,每次增光前,先跑一遍 SPFA,然后重新标注边权。

时间复杂度

我不会。长大后再知道是 $O(nm|f|)$ (朴素)或 $O(m \log m |f|)$ (原始对偶) 吧。

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计