带Boost的最小生成树
Minimum Spanning Tree with Boost
生成无向图的代码如下:
// --- 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& 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。它非常强大,但不容易理解。
TLDR: use
kruskal_minimum_spanning_tree(g, std::back_inserter(mst),
weight_map( get(&Edge::weight, g) );
原始回答:
你面临的问题是算法需要访问图的权重图,而你的算法默认没有权重图。如果你看一下文档中算法的签名你可以看到它是:
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<P, T, R>& params
。最后一个参数允许您使用该页后面列出的四个参数:weight_map
、rank_map
、predecessor_map
和vertex_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
(或任何其他算法),那么捆绑属性根本没用。您只需要使用命名参数覆盖默认的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(&Struct::member, g)
。
关于命名参数的最后注意事项,如果在算法调用中需要使用多个这些参数,则需要将它们与.
连接起来,而不是通常的,
,因为在签名中params
尽管其名称是单个参数。
//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));
下面是一个示例,它显示了类似于使用内部属性和绑定属性的东西。它故意使用不同的方式来设置/访问属性,以显示您可以做什么。
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- boost::variant - 对变体应用算术的最简单方法
- 通过boost asio iostream下载大文件的最快方法是什么?
- boost::bind函数缓冲区的最大大小
- 使用 Prim 算法计算最小生成树:如何使其简单?
- C++中Boost库的cpp_dec_foat的最大值是多少
- 使用非连接存储(即!= vecs)和add_Edge()的最小boost aidgacency_list
- Boost::ASIO:针对最小流量、长连接、小消息、即时传递进行优化
- Boost R-Tree中的最小边界矩形计算
- C 使用Boost库的C 最小跨越树
- 提升最小生成树,如何先做深度
- Prim 和 Boruvka 的最小生成树算法
- 使用最小生成树(C/C++)查找从A到B的路径
- 尝试使用书中的最小生成树示例,但它不适用于大数据
- 如何使用 Prim 算法从输入文件中查找具有给定坐标集的最小生成树?
- 使用 Kruskal 算法查找最小生成树的错误
- Kruskal的最小生成树算法
- 带Boost的最小生成树
- 在实现最小生成树的 Prim 算法时,逻辑错误是什么?
- 使用prim算法的最小生成树,不知道出了什么问题