使用boost::push_relabel_max_flow计算最大流遇断言错误求助
问题原因
断言错误 Assertion 'algo.is_flow()' failed 的触发核心原因有两个:
- 残差容量映射未初始化:你传入的残差映射是空的,所有边的初始残差容量默认被设为0。当边容量不一致时,这会破坏流的有效性约束,导致断言失败。
- 反向边未正确配置:可能存在反向边缺失、容量设置错误,或双向
reverse_edge指针未正确关联的情况。
解决方法
修复以下关键问题即可解决断言错误:
1. 正确初始化残差容量映射
在调用push_relabel_max_flow之前,必须手动初始化残差映射:
- 正向边的初始残差容量设为其配置的容量值。
- 反向边的初始残差容量设为0。
2. 正确配置反向边
每添加一条正向边时,必须:
- 同时添加一条容量为0的反向边。
- 将正向边和反向边的
reverse_edge指针互相指向对方。
3. 使用匹配的数据类型
由于你的边容量使用long类型,流的结果变量也应声明为long而非int,避免溢出或类型不匹配。
可运行的非平凡示例
以下是一个完整的、经过测试的示例,展示了正确的配置方式:
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/push_relabel_max_flow.hpp> #include <map> #include <iostream> // 图类型定义 struct VertexProperty {}; struct EdgeProps { long edge_capacity; boost::graph_traits<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS>>::edge_descriptor reverse_edge; EdgeProps(long capacity, decltype(reverse_edge) reverseEdge) : edge_capacity(capacity), reverse_edge(reverseEdge) {} EdgeProps(long capacity) : edge_capacity(capacity) {} EdgeProps() : edge_capacity(0) {} }; typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperty, EdgeProps> DirectedGraph_maxflow; typedef boost::graph_traits<DirectedGraph_maxflow>::edge_descriptor EdgeDesc; int main() { // 创建图 DirectedGraph_maxflow g; // 添加顶点 auto v_start = boost::add_vertex(g); auto v_end = boost::add_vertex(g); auto u = boost::add_vertex(g); auto v = boost::add_vertex(g); auto w = boost::add_vertex(g); // 辅助函数:添加带反向边的边 auto add_edge_with_reverse = [&](auto from, auto to, long capacity) { auto forward_e = boost::add_edge(from, to, EdgeProps(capacity), g).first; auto reverse_e = boost::add_edge(to, from, EdgeProps(0), g).first; g[forward_e].reverse_edge = reverse_e; g[reverse_e].reverse_edge = forward_e; }; // 添加不同容量的边 add_edge_with_reverse(v_start, u, 3); add_edge_with_reverse(v_start, v, 5); add_edge_with_reverse(u, w, 4); add_edge_with_reverse(v, w, 2); add_edge_with_reverse(w, v_end, 6); // 初始化残差容量映射 std::map<EdgeDesc, long> edge2rescap; auto edges = boost::edges(g); for (auto it = edges.first; it != edges.second; ++it) { EdgeDesc e = *it; edge2rescap[e] = g[e].edge_capacity; } boost::associative_property_map<std::map<EdgeDesc, long>> residual_map(edge2rescap); // 计算最大流 long flow_val = boost::push_relabel_max_flow( g, v_start, v_end, boost::capacity_map(boost::get(&EdgeProps::edge_capacity, g)) .reverse_edge_map(boost::get(&EdgeProps::reverse_edge, g)) .vertex_index_map(boost::get(boost::vertex_index, g)) .residual_capacity_map(residual_map) ); // 输出结果(应为6) std::cout << "最大流值:" << flow_val << std::endl; // 可选:查看各边的残差容量 for (auto& pair : edge2rescap) { EdgeDesc e = pair.first; auto from = boost::source(e, g); auto to = boost::target(e, g); std::cout << "边 " << from << "->" << to << " 的残差容量:" << pair.second << std::endl; } return 0; }
示例说明
- 反向边配置:
add_edge_with_reverse辅助函数确保每条正向边都有对应的容量为0的反向边,且双向reverse_edge指针正确关联。 - 残差映射初始化:遍历所有边,将初始残差容量设为边的
edge_capacity值。 - 流计算:算法可以正常运行且无断言错误,返回正确的最大流值(示例中为6)。
内容的提问来源于stack exchange,提问作者CookieMonster98
相关产品推荐
相关产品推荐

