网络流

网络流 Network flow

flowchart LR S(Source) v1([V1]) v2([V2]) v3([V3]) v4([V4]) t(sink) S -->|4| v1 S -->|2| v2 v1 -->|1| v2 v2 -->|2| v4 v1 -->|4| v4 v1 -->|2| v3 v4-->|3|t v3-->|3|t

有向有权图,Source为起点,Sink为终点。

阻塞流 blocking flow

flowchart LR S a@-->|2/2| v1 v1 b@-->|1/1| v2 S -->|0/2| v2 v1 c@-->|1/2|T v2 d@-->|1/1|T a@{ animation: fast } b@{ animation: slow } c@{ animation: slow } d@{ animation: slow }

无法让更多的水流过。

如何找到一种阻塞流方案

Residual (空闲量) Graph (图)

空闲量=管道最大流量-实际流量;

  1. 随便找一条从起点到终点的路径。
  2. 计算该路径可通过的最大流量,更新空闲量。
  3. 重复,若找不到路径就结束。
flowchart LR S(Source) v1([V1]) v2([V2]) v3([V3]) v4([V4]) t(sink) S ==>|4-3=1| v1 S -->|2| v2 v1 -->|1| v2 v2 -->|2| v4 v1 ==>|4-3=1| v4 v1 -->|2| v3 v4==>|3-3=0|t v3-->|3|t
flowchart LR S(Source) v1([V1]) v2([V2]) v3([V3]) v4([V4]) t(sink) S ==>|1-1=0| v1 S -->|2| v2 v1 -->|1| v2 v2 -->|2| v4 v1 -->|1| v4 v1 ==>|2-1=1| v3 v4 -.-> t v3==>|3-1=2|t

没有从起点到终点的路径,找到阻塞流

最大流 Maximum flow

将边看成一些水管,水管有最大流量限制。从起点注水,求网络能承载的最大流量,即注水口和出水口的最大流量,每根管道的流量不能超过其最大流量。

Ford-Fulkerson Algorithm

  1. 随便找一条从起点到终点的路径。
flowchart LR S(Source) v1([V1]) v2([V2]) v3([V3]) v4([V4]) t(sink) S a@==> |4-3=1| v1 S --> |2| v2 v1 -->|1| v2 v2 -->|2| v4 v1 b@==>|4-3=1| v4 v1 -->|2| v3 v4 c@==>|3-3=0|t v3-->|3|t a@{ animation: fast } b@{ animation: fast } c@{ animation: fast }
  1. 该路径可通过最大流量为3,更新空闲量。

  2. 添加反向路径

flowchart LR S(Source) v1([V1]) v2([V2]) v4([V4]) v3([V3]) t(sink) S -->|1| v1 S -->|2| v2 v1 -->|1| v2 v2 -->|2| v4 v1 -->|1| v4 v1 -->|2| v3 v4 ~~~t t a@-.->|3|v4 v4 b@-.->|3|v1 v1 c@-.->|3|S v3 -->|3|t a@{ animation: slow } b@{ animation: slow } c@{ animation: slow }
  1. 重复第一步,找一条从起点到终点的路径。
flowchart LR S(Source) v1([V1]) v2([V2]) v4([V4]) v3([V3]) t(sink) S -->|1| v1 S a@==>|2| v2 v1 -->|1| v2 v2 b@==>|2| v4 v1 -->|1| v4 v1 d@==>|2| v3 v4 ~~~t t -.->|3|v4 v4 c@-.->|3|v1 v1 -.->|3|S v3 e@==>|3|t a@{ animation: fast } b@{ animation: fast } c@{ animation: fast } d@{ animation: fast } e@{ animation: fast }
  1. 最大流量为2,更新空闲量。
flowchart LR S(Source) v1([V1]) v2([V2]) v4([V4]) v3([V3]) t(sink) S -->|1| v1 S ~~~ v2 v1 -->|1| v2 v2 ~~~ v4 v1 -->|1| v4 v1 ~~~ v3 v4 ~~~ t t -.->|3|v4 v4 -.->|1|v1 v1 -.->|3|S v3 -->|1|t
  1. 添加反向边,合并方向相同的边。
flowchart LR S(Source) v1([V1]) v2([V2]) v4([V4]) v3([V3]) t(sink) S -->|1| v1 v1 -->|1| v2 v1 c@--->|3| v4 t -.->|3|v4 v4 -.->|1|v1 v1 -.->|3|S v3 -->|1|t v2 a@-.->|2| S v4 b@-.->|2| v2 v3 d@-.->|2| v1 t e@-.->|2| v3 a@{ animation: slow } b@{ animation: slow } c@{ animation: fast } d@{ animation: slow } e@{ animation: slow }
  1. 找不到从起点到终点的路径,结束循环、

删除反向路径

flowchart LR S(Source) -->|1| v1([V1]) S ~~~ v2([V2]) v1 --> |1| v2 v2 ~~~ v4 v1 -->|3| v4([V4]) v1 ~~~ v3([V3]) v4~~~t(Sink) v3-->|1|t

计算流量

flowchart LR S(Source) v1([V1]) v2([V2]) v3([V3]) v4([V4]) t(sink) S -->|3| v1 S -->|2| v2 v1 -.-> v2 v2 -->|2| v4 v1 -->|1| v4 v1 -->|2| v3 v4-->|3|t v3-->|2|t

算法效率

Ford-Fulkerson Algorithm由于选择路径时的不确定性在一些情况下,速度非常慢。

举例:

flowchart LR S -->|1000| v1 v1-->|1| v2 S -->|1000| v2 v1-->|1000|T v2-->|1000|T

显然最大流为2000

若第一次选择路径 S->v1->T 或 S->v2->T则可以很快解决问题。

若选择 S->v1->v2->T 则需消耗较长时间。

flowchart LR S <-->|1\999| v1 v2 -.->|1| v1 S -->|1000| v2 v1-->|1000|T v2<-->|1\999|T
flowchart LR S <-->|1\999| v1 v1 -.->|1| v2 S <-->|1\999| v2 v1<-->|1\999|T v2<-->|1\999|T

在最坏情况下需要循环2000次。

Edmonds-Karp Algorithm

为了解决最坏情况下的效率问题,每次选取最短路径(不考虑边的权重)

时间复杂度:找最短路 \(O(edges)\),最多循环 \(edges\times vertices\)。最坏时间复杂度
\(O(edges^2 \times vertices)\) 证明比较复杂可以看原始论文。

Dinic's Algorithm

Yefilm Dinitz. Proceedings of the USSR Academy of Sciences, 11:
1277-1280, 1970.

阻塞流

最大流一定是阻塞流

阻塞流不一定是最大流,但无法让更多的水流过。

Level Graph 分层图

从起点出发走几步可以到达。

flowchart LR s(S/0) v1([3]) v2([1]) v3([3]) v4([2]) t(T/4) s <--> v2 v2 <--> v4 v1 <--> v4 v1 --> s v4 --> v3 v3 <--> t t --> v4 v2 --> v4
flowchart LR s(S/0) v1([1]) v2([1]) v3([2]) v4([2]) t(T/3) s --> v1 s --> v2 v1 --> v3 v1 --> v4 v2 --> v4 v3 --> t v4 --> t

计算最大流

  1. 构建 level graph
  2. 寻找阻塞流(更新空闲量)
  3. 如果找不到,break。
  4. 添加反向边
  5. goto 1

最坏时间复杂度 \(O(edges \times vertices^2)\)

posted @ 2025-12-07 17:01  ovida  阅读(2)  评论(0)    收藏  举报