
《把定理跑出来》系列收官之作。网络流是本科图论的最后一座山,也是前三讲所有工具的汇合点:增广路里跑着最短路式的搜索,匹配转化用着第 3 讲的多项式自信,Hall 定理的验证靠第 2 讲的遍历。
这一讲跑三件事:最大流最小割定理的对偶性 (100 组随机网络数值验证)、Edmonds-Karp 与 Dinic 的增广次数差距 (单位容量网络实测 5.8 倍)、二分图匹配的三方对拍与 Hall/Konig 双定理。全文 8 张图由文末代码生成,种子固定,可复现。
摘要
- 最大流最小割定理 :100 组随机网络实测------每组网络的最大流值与最小割容量严格相等(图 1 的实例里,流值 3 = 两条入汇边的容量 1+2);对偶性让"瓶颈"从约束变成答案;
- Edmonds-Karp vs Dinic :单位容量二分匹配网络上(half=400,总点 802),EK 37.69ms vs Dinic 6.48ms(5.8 倍)------容量全 1 时增广次数 = 匹配数 ≈ 400 次 BFS,Dinic 的分层 phase 只有 O(√E) 个;
- 二分图匹配三方对拍 :Kuhn / Hopcroft-Karp / 最大流转换,n=30~240 四档规模答案完全一致 ;速度分层------HK 在 n=240 时比 Kuhn 快 10.5 倍;
- Hall 定理 :min(|N(S)|−|S|) ≥ 0 ⟺ 存在饱和左部的匹配,400 组随机二分图全对;实测反例:7 个任务的可做集合只有 5 个志愿者------|N(S)|−|S| = −2,落单是数学必然;
- Konig 定理 :最大匹配 = 最小点覆盖,构造法验证 200/200------从最大匹配沿交替路标记,"未标记左点 + 已标记右点"就是一个合法点覆盖;
- 应用闭环:8 任务 × 6 志愿者的分配问题------最大匹配 6,2 个任务落单是 Hall 条件的必然而非调度不力。
关键词:网络流;最大流最小割定理;Edmonds-Karp;Dinic;二分图匹配;匈牙利算法;Hopcroft-Karp;Hall 定理;Konig 定理;对偶性
目录
- [1. 网络流:给图加一个"运输"的语义](#1. 网络流:给图加一个"运输"的语义)
- [2. 最大流最小割定理:对偶性让瓶颈自己现形](#2. 最大流最小割定理:对偶性让瓶颈自己现形)
- [3. Edmonds-Karp vs Dinic:增广次数的差距](#3. Edmonds-Karp vs Dinic:增广次数的差距)
- [4. 二分图匹配 = 单位容量最大流](#4. 二分图匹配 = 单位容量最大流)
- [5. Hall 定理:落单是数学必然](#5. Hall 定理:落单是数学必然)
- [6. Konig 定理:最大匹配 = 最小点覆盖](#6. Konig 定理:最大匹配 = 最小点覆盖)
- [7. 系列收官:六讲的知识地图](#7. 系列收官:六讲的知识地图)
- [8. 复现指南](#8. 复现指南)
- [9. 写在最后](#9. 写在最后)
1. 网络流:给图加一个"运输"的语义
网络 = 有向图 + 边容量(这条边最多能"运"多少)+ 源点 s 和汇点 t。"最大流"问的是:从 s 到 t,单位时间最多能运多少?
它在课程里的位置非常微妙------前面学的遍历、最短路、MST 都是"一个算法解一类题",而网络流的正确性来自一条深刻的对偶定理:
最大流最小割定理(Ford--Fulkerson, 1956):一个网络的最大流值,等于把顶点切成两半时"跨割容量之和"最小的那个割的容量。
这句话意味着:优化问题(最大流)的答案,和约束问题(最小割)的答案,是同一个数。第 3 篇第一次见到这个结构(MST 的瓶颈性质),这一讲它是主角。
2. 最大流最小割定理:对偶性让瓶颈自己现形
实验:100 组随机网络(n=6~12,边容量 1~9 随机),每组分别求最大流(Dinic)和最小割(残量网络中从 s 出发的可达集 S,跨割容量):

图 2:100/100 组------最大流值与最小割容量严格相等。
看一个具体实例(图 1):

图 1:12 点随机网络,流值 3 = 最小割容量 3。 红色两条边(7→11 容量 1、10→11 容量 2)是汇点 t 仅有的入边------算法没有被告知"t 的入边是瓶颈",是对偶性让瓶颈自己现形。这就是最小割定理最迷人的地方:你不用猜瓶颈在哪,跑完最大流它自动浮出来。
工程对应物:第 1 篇第 6 节的"跨河通勤能力腰斩 53%"------那时我们就用过这个定理,只是没有点名。
3. Edmonds-Karp vs Dinic:增广次数的差距
求最大流的两代经典算法都基于"增广路":找一条 s→t 的可行路径推流,重复到无路可增。
- Edmonds-Karp :每次 BFS 找最短增广路,O(VE²);
- Dinic :BFS 分层 + DFS 找阻塞流,O(V²E)。
纯看复杂度差别不大。但把网络换成单位容量的二分匹配网络(容量全 1 时增广次数 = 匹配数,每次增广 EK 都要一次全图 BFS,而 Dinic 的分层 phase 只有 O(√E) 个):

图 3:half 从 10 到 400。 half=400(总点 802)时 EK 37.69ms vs Dinic 6.48ms(5.8 倍)------而且 EK 曲线的斜率明显更陡(增广次数随规模线性涨、每次 BFS 全图扫)。
一个诚实的补充:随机大容量图上两者几乎打平(几轮增广就满流)------算法差距只在"增广次数多"的网络上显形。这也是选型的真实逻辑:先想清楚你的图属于哪种形态。
4. 二分图匹配 = 单位容量最大流
第 2 篇讲派单时预告过:二分图最大匹配可以转成最大流------加超级源 S 连左部(容量 1)、右部连超级汇 T(容量 1)、左到右的可行边容量 1。匹配数 = 最大流值。
课程版三方对拍:同一个二分图,Kuhn(匈牙利增广)、Hopcroft-Karp(分层增广)、最大流转换(Dinic),n=30~240 四档:

图 4:左:三种算法的匹配数逐点一致(断言保证);右:耗时分层------n=240 时 Kuhn 4.52ms、HK 0.43ms(快 10.5 倍)、最大流转换 4.70ms。
这张图把两条线索焊在了一起:匹配 = 流(定理),HK = Dinic 的二分图特化(直觉)------二分图的层次结构让 Dinic 的 phase 数恰好变成 O(√V),于是 HK 就是"Dinic 特化的匹配算法"。学懂了网络流,匹配算法全家桶免费附赠。
5. Hall 定理:落单是数学必然
匹配数 < 任务数时, managers 的第一反应是"调度不力"。Hall 定理说:未必------有些落单是数学必然。
Hall 定理:存在饱和全部左点的匹配 ⟺ 对任意左点子集 S,|N(S)| ≥ |S|(它们的邻居至少和它们一样多)。
实测 400 组随机二分图:min(|N(S)|−|S|) ≥ 0 与"存在饱和左部的匹配"400/400 完全一致(min 用小规模枚举全部 S⊆L 计算,匹配用 HK 计算------两个独立方法)。

图 5:实测反例。 8 个任务里前 7 个的可做集合只有 5 个志愿者------|N(S)|−|S| = 5−7 = −2 < 0,Hall 条件违反:无论调度器多聪明,至少 2 个任务落单。
Hall 条件的价值在于"一眼可查":不用跑匹配算法,扫一遍每个任务子集的邻居数就能预判匹配结果。这就是它比"试一试"高级的地方。

图 5b:应用闭环。 8 任务 × 6 志愿者的分配实例:最大匹配 6,任务 4、5 落单(红圈)------绿边是选中的指派,落单是 Hall 条件的必然而非调度不力。
6. Konig 定理:最大匹配 = 最小点覆盖
二分图的第二个对偶定理:最大匹配的边数 = 最小点覆盖的点数(选最少的顶点,让每条边至少碰到一个)。
构造法验证:从最大匹配出发,沿"非匹配边(左→右)、匹配边(右→左)"从所有未匹配左点做交替路标记------未标记的左点 + 已标记的右点就是一个最小点覆盖:

图 6:200 组随机二分图,构造出的点覆盖全部合法(每条边至少一端被盖)且大小恰等于最大匹配数------200/200。
应用原型:用最少的摄像头盯住所有通道、用最少的拦截点切断所有走私路线、用最少的补丁盖住所有漏洞------凡"选最少的点覆盖所有的边",都是 Konig 在工作。
7. 系列收官:六讲的知识地图

图 8:六讲知识地图。 从第 1 讲的握手定理到本讲的 Hall/Konig,每一讲都是同一个动作:课本给结论,我们造样本,让结论在数据里再发生一次。
六讲的数字账本:
| 讲次 | 验证的定理/结论 | 关键实测 |
|---|---|---|
| 第 1 讲 概念与存储 | 握手定理、计数公式、度分布 | 5 类图全等;存储边界反转 |
| 第 2 讲 遍历与连通 | O(n²)/O(n+e)、相变 | 序列差异 91%;138 倍;c=ln n |
| 第 3 讲 欧拉与哈密顿 | 判定×构造、规模墙 | 900+200 组对拍;NP 完全露脸 |
| 第 4 讲 最短路三件套 | 负权失效、Floyd 的 k | 误差 100%;路径重建 30/30 |
| 第 5 讲 生成树与拓扑 | 切割性质、关键路径 | 1429/1429;延误实验 |
| 第 6 讲 网络流与匹配 | 对偶性、Hall/Konig | 100/100;400/400;200/200 |
8. 复现指南
graph-course/
├── course6.py # 六组实验(对偶/横评/匹配三方/Hall/Konig/应用,~330 行)
├── figs6.py # 8 张配图
├── results/course6.json
└── figures/
bash
python course6.py # → results/course6.json(约 1 分钟)
python figs6.py # → 8 张图
依赖:本讲复用第 1 篇的 Dinic 骨架(sys.path 引入 graph-blog/kernel.py)。正确性断言:EK/Dinic 流值相等(每档规模)、匹配三方对拍一致(assert)、Hall 与匹配存在性 400 组一致、Konig 构造 200 组合法且等大小。种子 SEED=2026,确定性结果逐字节一致。
9. 写在最后
六讲写完,这个系列想传达的方法只有一条:
图论的每一个定理,都值得在计算机里重新"发生"一次。 背下来的握手定理会忘,跑过的 264 = 264 不会;抄来的"Hopcroft-Karp 快"没有体感,亲手对拍出的 12.7 倍才是选型时的肌肉记忆;教科书上"NP 完全"四个字很抽象,亲眼看一次回溯在阈值附近超时 22/25 就再也不会误解它。
以及最重要的------当算法给你的答案违反直觉时,先怀疑模型的假设,再怀疑算法的实现,最后才轮到接受"反直觉"本身。第 4 讲的单位换算 bug、第 5 讲的 vl/ve 混用、本讲第一版割容量把"入边"也算了进去------每一次"错误的结果"背后都是一个值得写进博客的洞见。
数据不会说谎,但会考验你提问的方式。
系列完结。六讲全部代码与数据:
graph-course/(course1~6.py + figs*.py + results/*.json)。祝每一场考试、每一次面试、每一个工程决策,都有跑出来的数据撑腰。
系列目录:第 1 讲 基本概念与存储 · 第 2 讲 遍历与连通 · 第 3 讲 欧拉图与哈密顿图 · 第 4 讲 最短路三件套 · 第 5 讲 生成树与拓扑排序 · 第 6 讲 网络流与匹配(本篇,完结)