最大流简陋小记

posted on 2023-11-14 11:45:13 | under 笔记 | source

起因是某次模拟考出现二分图最大匹配,但是故意卡掉匈牙利只能用网络流,于是快速学了下。

超级简陋,之后或许会重写?

基本概念

想象一座城市的水网:

  • 网络:水网。
  • 源点 \(s\):有源源不断地水,相当于水厂。
  • 汇点 \(t\):所有水最终汇入此处,相当于你家。
  • 边:一条有向边,也可称弧。
  • 容量 \(e_c\):水管每单位时间可经过的水的上界。
  • 流量 \(e_f\):水管每单位时间内可经过的水。之后会用函数 \(f\) 的形式描述。
  • 残留容量 \(e_r\)\(e_r=e_c-e_f\),水管还可继续流经的水量。
  • 容量网络:边带容量的网络。类比有流量 / 残量网络。
  • 网络的流量:\(\sum f(s,x)\)\(\sum f(x,t)\)。你家总共收到的水。

流量的函数表示 / 性质

  • 容量限制:\(e_f\le e_c\)
  • 流量守恒:\(\sum f(u,v)=0\),也可写为 \(\sum f(x,u) = \sum f(u,y)\)。有多少水流进来,就有多少水流出去。
  • 斜对称性:\(f(u,v) = -f(v,u)\),比较难理解但是很重要。

最大流

求如何分配水流,使得网络的流量最大?我们将这样分配下的流量网络称作最大流网络。

增广路定理

  • 增广路:在残量网络上一条从 \(s\)\(t\) 的路径,满足边的残量均 \(>0\)
  • 增广路定理:该网络是最大流网络,当且仅当不存在增广路。

简单理解为:否则可以走这条增广路使得流量增加。

EK 算法

一种容易想到的思路是:建出残量网络,然后不断走增广路。

该算法流程如下:

  1. 初始化残量网络:\(r(u,v)=c(u,v),r(v,u)=0\)

  2. \(\rm bfs\) 找到最短增广路。

  3. 设增广路上最小残量是 \(minr\),则对其路上的所有 \(e(u,v)\) 都:\(r(u,v)-minr\),为了满足斜对称性对其反边 \(r(v,u)+minr\)。答案增加 \(minr\)

  4. 重复 \(2,3\) 直到不存在增广路。

比较难理解的是反边(因为增广路可以由反边构成!),而且对边操作后其反边的残量还会增加,比较玄幻。

可以理解为正边的反悔标记。每次对 \((v,u)+minr\),就等于撤销 \((u,v)\)\(minr\) 单位流量,并转移到增广路上使得答案增加.

而对于 \((v,u)-minr\) 的操作,建议看图手模下。大概思路:撤回曾经那次增广路操作 \(minr\) 容量,让它走旧路经前半和新路径后半到达 \(t\),并使得多出 \(minr\) 残量(相当于答案不变的情况下还能多出残量)。可以让 \(minr\) 流量走新路径前半和旧路径后半到达 \(t\)。总计 \(ans+minr\)

EK

dinic 算法

发现 \(\rm EK\) 算法每次只能更新一条增广路,能否同时更新多条呢?

\(\rm dinic\) 算法就实现了该思路,具体如下:

  1. \(\rm bfs\) 求出原图的最短增广路,并根据访问次序标上层级(建分层图)。

  2. \(\rm dfs\) 在分层图上同时更新多条增广路。

  3. 重复 \(1,2\) 知道不存在增广路。

关于第二步,具体如下:\(\rm dfs\) 过程中同时下传 \(sum\) 表示 \(s\to u\) 的增广路上最小边权,并在结束时返回 \(s\to u\to t\) 的所有增广路可更新的流总和 \(res\)。令下一层 \(v\) 的返回值为 \(k\),则可以更新增广路的 \(s\to u\) 部分的残量,于是有 \(sum-k\),同时 \(res+k\)

不加优化复杂度错误,先说 当前弧优化:对于每个 \(u\),若 \(v_1...v_p\) 都被遍历了,则 \(s\to u\to v_j\to t\) 的所有增广路都被流满了(存在残量为 \(0\) 的边),因此不需再访问。可以用 \(now_u\) 记录下次要访问的边,不断推进即可。

还有一些剪枝,具体见代码。

dinic

最小割

  • 割:是指有向图一边集,使得删去后 \(s\to t\) 不连通。
  • 最小割:边权和最小的割。

首先有个最大流 \(=\) 最小割的定理。

理解:显然所有流都经过最小割,否则不符合定义,故最小割 \(\ge\) 最大流;再考虑最大流的最终局面,会存在一些满流边,显然最大流是从这些边得来的(瓶颈),那么它们必须构成割,否则仍存在增广路,故最小割 \(\le\) 最大流。综上定理得证。

关于最小割的方案输出:不难发现 \(s\to\) 最小割的流必定 \(>0\),而最小割上的边均为满流边。具体的,可以用 \(\rm bfs/dfs\) 从源点开始走残量为正的边,并标记所到的点。这里不能直接找残量为 \(0\) 的边的原因是避免重复,满流边并不总是处于最小割,但最小割一定是满流边

一条边的起点被标记而终点未标记,则说明其属于最小割。

(注意去除反边)

posted @ 2026-01-15 08:24  Zwi  阅读(2)  评论(0)    收藏  举报