c++ - boost dijkstra 弦边权重

标签 c++ c++11 boost dijkstra boost-graph

是否可以使用字符串值代替 double 属性 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))));

错误:

Error 13 error C2664: 'D boost::closed_plus::operator ()(const T &,const T &) const' : cannot convert argument 2 from 'const std::basic_string,std::allocator>' to 'const D &' C:\boost_1_58_0\boost\graph\dijkstra_shortest_paths.hpp 190

最佳答案

是的,你可以有一个字符串属性。

不,dijkstra 需要

a weighted, directed or undirected graph for the case where all edge weights are nonnegative

所以权重需要是数字。当然,如果你能实现算术运算和 std::numeric_limit<>对于您的属性(property)类型来说,这可能没问题(但在这样做之前您确实必须挠头)。

更新 _实际上,事实证明该文档简化了一点,您实际上可以覆盖零、比较和组合您的权重类型。请参阅linked sample在评论中(HT @cv_and_he)_

所以,我讨厌成为那样的人,但是:为什么

既然权重是任何单位的数量,那么将它们存储为字符串的目标是什么?您是否可能遇到不同的问题,导致您无法正确存储权重?


也就是说,这是一种方法:

使用transform_value_property_map您可以将字符串即时转换为 double :

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];
}

渲染为

enter image description here

关于c++ - boost dijkstra 弦边权重,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34878147/

相关文章:

c++ - OpenCV - 从视差图计算实际距离

c++ - xxxxx 处的未处理异常无法写入位置。它不会在 getline 之外执行......在 visual studio 2010 中

c++ - 模板元代码和私有(private)成员

C++清除队列和线程安全

c++ - 包含单个 boost posix_time.hpp header 时编译错误

c++ - 如何更改 dynamic_bitset 的值?

c++ - 如何在接收类之外声明嵌套类的方法

c++ - 常量变量与常量引用

c++ - 对象构造 : default parameter vs delegation

c++ - 你能用 C++ 做一个计算 goto 吗?