【问题标题】:Minimum Spanning Tree with Boost带 Boost 的最小生成树
【发布时间】:2016-10-07 00:51:01
【问题描述】:

我有以下生成无向图的代码:

// --- Header File ---
class Node { ... };
struct Edge { float weight; };
typedef adjacency_list<vecS, vecS, undirectedS, Node, Edge> Grafo;

class MST
{
    public:
        MST(std::vector<Node> nodes);
        Grafo g;
        vector<edge_t> build();
};

// --- cpp File ---
MST::MST(std::vector<Node> nodes) {  // build the graph by setting vertices and edges...  }

vector<edge_t> MST::build()
{
    vector<edge_t> mst;
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst));
    return mst;
}

问题在于我称之为 Kruskal 的那一行:kruskal_minimum_spanning_tree()。如果我评论这一行,它会编译得很好,我可以用 graphviz 导出图表(你可以在webgraphviz.com 看到图表):

graph G {
0[label="a"];
1[label="b"];
2[label="c"];
3[label="d"];
4[label="e"];
0--1 [label=80.4487381];
0--2 [label=406.060333];
0--3 [label=405.738831];
0--4 [label=434.203857];
1--2 [label=25.9422436];
1--3 [label=210.344955];
1--4 [label=246.965591];
2--3 [label=35.805027];
2--4 [label=35.1283379];
3--4 [label=167.5858];
}

但是,如果我尝试使用该行进行编译,我会从 Boost 中得到很多错误(我使用的是 g++ 4.9.2)。第一个错误是:error: forming reference to void typedef value_type&amp; reference;,这个错误重复了好几次。出现的其他错误:

error: no matching function for call to 'get(boost::edge_weight_t, const boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Symbol, Edge>&)'
        get(edge_weight, g));

所以我尝试在调用 Kruskal 方法之前添加get(edge_weight, g);,但我得到了注释:

note:   types 'boost::subgraph<Graph>' and 'const boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Symbol, Edge>' have incompatible cv-qualifiers
        get(edge_weight, g));

note:   mismatched types 'const boost::two_bit_color_map<IndexMap>' and 'boost::edge_weight_t'
        get(edge_weight, g));

我不知道该怎么办。这是我第一次使用 Boost Graph Library。它非常强大,但并不容易理解。

【问题讨论】:

    标签: c++ boost boost-graph


    【解决方案1】:

    TLDR:使用

    kruskal_minimum_spanning_tree(g, std::back_inserter(mst), 
                            weight_map( get(&Edge::weight, g) );
    

    原答案

    您面临的问题是该算法需要访问图表的权重图,而您的默认情况下没有。如果您查看the documentation 中的算法签名,您可以看到它是:

    template <class Graph, class OutputIterator, class P, class T, class R>
    OutputIterator kruskal_minimum_spanning_tree(Graph& g, OutputIterator tree_edges, 
                                       const bgl_named_params<P, T, R>& params = all defaults);
    

    它有两个“正常”参数(您使用的那些),然后是一个看起来很奇怪的bgl_named_params&lt;P, T, R&gt;&amp; params。最后一个参数允许您使用该页面后面列出的四个参数:weight_maprank_mappredecessor_mapvertex_index_map。如果您不使用任何这些参数,则使用其默认值,对于weight_map,此默认值为get(edge_weight,g)。这仅在您的图表中有内部 edge_weight 属性时才有效,这意味着您的图表定义如下:

    typedef adjacency_list<vecS, vecS, undirectedS, 
                        property<vertex_name_t,char>,//Could also be `Node` unless you use another algorithm with requirements on the vertices
                        property<edge_weight_t,float> 
                      > InternalPropGraph;
    

    但如果使用kruskal_minimum_spanning_tree(或任何其他算法)需要该定义,那么bundled properties 将完全没有用处。您只需要使用命名参数覆盖默认的weight_map

    //typedef adjacency_list<vecS, vecS, undirectedS, Node, Edge> Grafo;
    ...
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst), 
                            weight_map( get(&Edge::weight, g) );
    

    要访问将顶点/边描述符与结构成员相关联的属性映射,您只需使用get(&amp;Struct::member, g)

    关于命名参数的最后一点说明,如果在调用算法时需要使用多个这些参数,则需要将它们与. 连接,而不是通常的,,因为在签名@987654340 @ 尽管它的名字是一个参数。

    //the order of the named params is irrelevant
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst), 
                                     weight_map(my_weights)
                                    .vertex_index_map(my_indices)
                                    .predecessor_map(my_predecessors));
    

    Here 是一个示例,它使用内部属性和捆绑属性显示类似于您想要的内容。它故意使用不同的方式来设置/访问属性来展示你可以做什么。

    【讨论】:

    • 成功了。现在我有了关于“财产申报”的想法。您给了我一个 Boost 课程,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-10-16
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多