求助:使用boost::dijkstra_shortest_paths计算带顶点权重的最短路径报错
解决Boost Dijkstra算法中自定义顶点+边权重的问题
你的问题出在Boost的weight_map参数要求符合可读属性映射(ReadablePropertyMap)概念,直接传递lambda无法满足这个要求——lambda没有Property Map所需的嵌套类型(如value_type、key_type)和标准接口,导致运行时类型检查失败。
下面是两种可行的解决方案:
方案一:用function_property_map包装lambda
Boost提供了function_property_map工具,可以将普通函数或lambda转换成合法的Property Map。
- 先包含对应的头文件:
#include <boost/property_map/function_property_map.hpp>
- 修改自定义权重映射的定义:
// 用make_function_property_map包装lambda,明确键类型为Graph::edge_descriptor auto custom_weight_map = boost::make_function_property_map<Graph::edge_descriptor>( [&g](const Graph::edge_descriptor& e) -> float { float vertex_weight = g[target(e, g)].weight; float edge_weight = get(boost::edge_weight, g, e); return vertex_weight + edge_weight; } );
- 原Dijkstra调用代码保持不变,此时
custom_weight_map已符合要求,可以正常传入。
方案二:预处理合并顶点与边权重
如果不需要保留原始边权重,可以直接遍历所有边,将目标顶点的权重合并到边的权重中,这样无需自定义权重映射。
// 遍历所有边,将目标顶点权重合并到边权重 for (auto e : boost::make_iterator_range(edges(g))) { auto target_v = target(e, g); float combined = get(boost::edge_weight, g, e) + g[target_v].weight; put(boost::edge_weight, g, e, combined); } // 直接使用默认的edge_weight_map调用Dijkstra boost::dijkstra_shortest_paths( g, source_vertex, boost::predecessor_map( boost::make_iterator_property_map( predecessors.begin(), boost::get(boost::vertex_index, g))) .distance_map(boost::make_iterator_property_map( distances.begin(), boost::get(boost::vertex_index, g))));
注意事项
如果需要将起点的顶点权重计入总路径长度,需要手动初始化距离数组:
distances[source_vertex] = g[source_vertex].weight;
因为自定义权重映射只统计每条边目标顶点的权重,起点不会被任何边指向,默认初始距离为0,不会包含其自身权重。
内容的提问来源于stack exchange,提问作者dongchen
相关产品推荐
相关产品推荐

