最大流简陋小记

· · 个人记录

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

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

基本概念

想象一座城市的水网:

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

EK 算法

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

该算法流程如下:

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

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

  3. 重复 2,3 直到不存在增广路。

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

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

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

EK

dinic 算法

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

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](https://www.luogu.com.cn/paste/asuwa5gy) ### 最小割 * 割:是指有向图一边集,使得删去后 $s\to t$ 不连通。 * 最小割:边权和最小的割。 首先有个最大流 $=$ 最小割的定理。 理解:显然所有流都经过最小割,否则不符合定义,故最小割 $\ge$ 最大流;再考虑最大流的最终局面,会存在一些满流边,显然最大流是从这些边得来的(瓶颈),那么它们必须构成割,否则仍存在增广路,故最小割 $\le$ 最大流。综上定理得证。 关于最小割的方案输出:不难发现 $s\to$ 最小割的流必定 $>0$,而最小割上的边均为满流边。具体的,可以用 $\rm bfs/dfs$ 从源点开始走残量为正的边,并标记所到的点。这里不能直接找残量为 $0$ 的边的原因是避免重复,**满流边并不总是处于最小割,但最小割一定是满流边**。 一条边的起点被标记而终点未标记,则说明其属于最小割。 (注意去除反边)