是否可以使用字符串值而不是双重属性
typedef adjacency_list < vecS, vecS, directedS, property<vertex_name_t, string>, property < edge_weight_t, string> > Graph;
我的目标是使用dijkstra算法。
PS:我已经尝试用字符串替换double,它会在算法中产生错误。
std::vector<vertexd> P(num_vertices(g));
std::vector<string> d(num_vertices(g));
vertexd s = vertex(0, g);
dijkstra_shortest_paths(g, s,
predecessor_map(boost::make_iterator_property_map(P.begin(), get(boost::vertex_index, g))).
distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g))));
错误:
错误13错误C2664:'D boost :: closed_plus :: operator()(const T&amp;,const T&amp;)const':不能从'const std :: basic_string,std :: allocator&gt;转换参数2 “ 'const D&amp;' C:\ boost_1_58_0 \ boost \ graph \ dijkstra_shortest_paths.hpp 190
答案 0 :(得分:2)
是的,你可以拥有一个字符串属性。
不,dijkstra要求
所有边权重为非负的情况下的加权,有向或无向图
所以重量必须是数字。当然,如果你可以为你的属性类型实现算术运算和std::numeric_limit<>
,那么它可能没什么问题(但是在你这样做之前你真的要抓住它)。
更新 _实际上,事实证明这个文档有点简化,你实际上可以覆盖你的体重类型的零,比较和组合。请参阅注释中的linked sample(HT @cv_and_he)_
所以,我讨厌那个人,但是:为什么。
因为权重是任何单位的金额,所以将它们存储为字符串的目标是什么?您是否可能有不同的问题阻止您正确存储权重?
那就是说,这是一种方式:
使用transform_value_property_map
,你可以动态地将字符串转换为双打:
<强> Live On Coliru 强>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dag_shortest_paths.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
using Weight = std::string;
//using Weight = double;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
boost::property<boost::vertex_name_t, std::string>,
boost::property<boost::edge_weight_t, Weight>
> Graph;
using vertexd = Graph::vertex_descriptor;
Graph generate();
int main() {
using namespace boost;
Graph g = generate();
std::vector<vertexd> P(num_vertices(g));
std::vector<double> d(num_vertices(g));
vertexd s = vertex(0, g);
auto to_double = [](Weight const& v) { return lexical_cast<double>(v); };
dijkstra_shortest_paths(
g, s,
weight_map (make_transform_value_property_map(to_double, get(edge_weight, g)))
.predecessor_map(make_container_vertex_map(P))
.distance_map(make_container_vertex_map(d))
);
boost::dynamic_properties dp;
dp.property("node_id", get(vertex_name, g));
dp.property("label", get(edge_weight, g));
write_graphviz_dp(std::cout, g, dp);
}
#include <boost/graph/random.hpp>
#include <boost/range/iterator_range.hpp>
#include <random>
Graph generate() {
using namespace boost;
std::mt19937 prng { std::random_device {} () };
Graph g;
generate_random_graph(g, 10, 20, prng);
for (auto v : make_iterator_range(vertices(g)))
put(vertex_name, g, v, "vertex" + std::to_string(v));
#if 0
// in case `Weight` is double
auto gen_weight = [&, dist=std::uniform_real_distribution<Weight>(0,1)] () mutable -> Weight {
return dist(prng);
};
#else
// in case `Weight` is std::string
auto randchar = [&, dist=std::uniform_int_distribution<>('0','9')] () mutable -> char { return dist(prng); };
auto gen_weight = [&] () {
Weight tmp(3, ' ');
std::generate(tmp.begin(), tmp.end(), randchar);
return tmp;
};
#endif
for (auto e : make_iterator_range(edges(g)))
put(edge_weight, g, e, gen_weight());
return g;
}
输出随机生成的图形,例如:
digraph G {
vertex0->vertex5 [label=503];
vertex0->vertex8 [label=653];
vertex0->vertex8 [label=931];
vertex1->vertex6 [label=022];
vertex1->vertex8 [label=536];
vertex1->vertex5 [label=400];
vertex1->vertex4 [label=056];
vertex3->vertex8 [label=555];
vertex4->vertex7 [label=052];
vertex4->vertex6 [label=542];
vertex4->vertex3 [label=024];
vertex5->vertex7 [label=595];
vertex5->vertex8 [label=850];
vertex7->vertex4 [label=464];
vertex7->vertex9 [label=484];
vertex8->vertex0 [label=274];
vertex8->vertex1 [label=131];
vertex8->vertex6 [label=529];
vertex9->vertex1 [label=239];
vertex9->vertex3 [label=362];
}
呈现为