Edmonds-Karp算法在C++中稳定求最大流的关键是正确建图与处理反向边:必须用邻接表(而非邻接矩阵)以支持重边;bfs需返回瓶颈流量值而非布尔值;反向边索引必须用id^1确保成对紧邻存储。

Edmonds-Karp 算法在 C++ 中能稳定求出最大流,关键不是“能不能”,而是“怎么建图”和“怎么避免反向边写错”——这两点踩坑的人最多。
为什么必须用邻接表存边,不能只用邻接矩阵?
邻接矩阵看似简单,但遇到重边(比如两条 u→v 边容量分别为 3 和 5)时,capacity[u][v] 只能存一个值,直接覆盖掉。而实际算法要求:正向边增广后,反向边要同步加流量,且每条边的残量必须独立追踪。
- 邻接表 +
vector方式可明确区分每条边,通过id和id^1快速定位反向边 - 邻接矩阵只能用于无重边、节点数 ≤ 200 的极小规模问题;一旦边数过百或存在重边,
add(u, v, c)就会 silently 错误累加或丢失 - 多数 OJ 题(如 POJ 1273、HDU 1532)默认含重边,用矩阵读入后跑出来结果偏大是常态
bfs() 返回的是路径瓶颈值,不是布尔值
很多初学者抄模板时把 bfs() 写成只返回 true/false,导致无法知道该沿路径推送多少流量,后续更新残量图就全乱了。
- 正确做法:返回
int类型的d[t](即从源点到汇点的最小剩余容量),若找不到路径则返回 0 或 -1 - 更新边流量时,必须用这个值:正向边减它,反向边加它;写成
f[id] -= d[T]而不是f[id]-- - 注意:
d[]数组存的是“到达该点的最小可行流”,不是距离;初始化d[s] = INF,其他为 0
反向边索引必须用 id^1,不能靠 id+1 或 id-1
这是最隐蔽也最致命的错误。所有标准实现都依赖边与反向边在 edges 容器中成对紧邻存储,且索引满足异或关系:edges[i] 和 edges[i^1] 互为正反向边。
- 添加边时必须成对调用:
edges.push_back(Edge(u,v,c,0))和edges.push_back(Edge(v,u,0,0)) - 更新时写
f[id] -= flow; f[id^1] += flow;—— 异或保证偶数索引对应正向、奇数对应反向,且不会越界 - 若手动用
id+1,当id是奇数时会指向错误边;用数组下标算术加减在动态push_back下极易失效
真正卡住人的从来不是算法逻辑,而是建图时漏了反向边初始化、BFS 中没传 bottleneck 值、或者更新时把 id^1 写成 id+1。这些地方一错,结果要么是 0,要么是远大于理论值的数,且调试时看不出哪条边被多加了流量。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











