
ford-fulkerson(含 edmonds-karp 实现)在残量网络中找不到增广路时自然终止,此时已达到理论最大流;所谓“重发剩余流量”本质上是误解——若算法结束仍不足目标值,说明该目标不可达,而非需手动重启。
ford-fulkerson(含 edmonds-karp 实现)在残量网络中找不到增广路时自然终止,此时已达到理论最大流;所谓“重发剩余流量”本质上是误解——若算法结束仍不足目标值,说明该目标不可达,而非需手动重启。
Ford-Fulkerson 算法的核心保证是:当 BFS(或 DFS)无法再找到从源点到汇点的增广路径时,当前流即为全局最大流。这意味着算法本身已穷尽所有可能的流量分配路径——包括正向边上的剩余容量,也包括反向边(即残量图中隐含的“撤销-重分配”能力)。因此,edmonds_karp() 函数返回后若 max_flow < target_flow,并非算法“没跑完”,而是数学上已证明:目标流量不可行。
在您的示例中,关键问题在于对“总流量”的定义混淆:
- ✅ 标准最大流定义:从源点(M01)到汇点(EXIT)的净流出量,等于所有指向 EXIT 的边上的实际流量之和(即 door_flows[→EXIT] 之和)。
- ❌ 您代码中的 actual_total_flow 计算的是 所有有向边上的流量总和(遍历 edges 列表累加 door_flows[u][v]),这不是网络流意义上的“总流量”,而是一个无物理意义的中间统计值。
验证这一点:观察您图中所有指向 EXIT 的边:
("M03", "EXIT", 15), # 容量 15
("M05", "EXIT", 25) # 容量 25
# → 理论最大流上限 = 15 + 25 = 40无论算法如何选择路径,整个网络的最大可能流严格 ≤ 40。您得到的 110 是所有边流量之和(例如 M01→M02, M02→M03, M03→M04 等路径上的重复计数),它反映的是“内部通道负载总和”,而非“成功撤离人数”。这解释了为何 target_flow = 120 不仅无法达成,连 40 都未必达到——您的 build_graph 未添加反向边初始化,且 bfs 逻辑虽正确,但 final_flow 函数中 actual_total_flow 的计算方式误导了结果解读。
⚠️ 注意事项:
- 不要尝试“二次运行”算法:残量图已饱和(无增广路),再次调用 bfs 必然返回 False,循环直接退出。
- 修正流量统计:若需输出合规的最大流值,请改为:
# 正确的最大流 = 所有进入汇点的流量之和 sink_idx = node_index["EXIT"] max_flow_correct = sum(door_flows[u][sink_idx] for u in range(len(nodes))) print(f"Maximum flow (source→sink): {max_flow_correct}")- 检查图建模:您期望路径 D01→D02→D04 在当前 edges 中并不存在(无 "M02", "M04" 边),需确认输入图是否与实际场景一致。
- 时间维度扩展(如需模拟疏散过程):若题目本意是“分分钟疏散120人”,则需构建时间展开图(time-expanded network),引入时间层节点(如 M01_t0, M01_t1...),将边容量转化为单位时间通过量,并求最小疏散时间——这已超出静态最大流范畴,属动态网络流问题。
综上,Ford-Fulkerson 的终止条件无需修改;真正需要修正的是:明确问题定义、校验图结构合理性、使用标准最大流定义评估结果。算法的优雅之处,正在于其终止即意味着最优性——无需人工干预或重试。

















