这是simple example。我建议使用邻接矩阵,因为该图将是完整的,因此矩阵非常密集。
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
现在让我们创建一个图表
int main() {
Graph g(23);
为本示例选取任意数量 (23) 个顶点。让我们使用随机生成的权重:
auto weight_distribution = std::bind(
std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
创建所有边以使图形完整:
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
现在,让我们使用 Prim 的算法(因为所有的权重都是非负的):
std::vector<Vertex> parent(num_vertices(g));
prim_minimum_spanning_tree(g, parent.data());
这会为parent 向量中的每个顶点写入前驱(称为前驱映射)。
添加一些输出
为了更有趣的结果,让我们添加一些检查和输出:
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
确保数据满足权重前提条件。您还可以根据获取输入数据的方式进行完整性检查。
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
让我们传递可选参数distance_map 和root_vertex:
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
使用命名参数(以boost::root_vertex 开头并以.other_parameter(...).even_more(...) 链接。您当然可以从任何命名参数开始)。
现在我们可以使用记录的数据了:
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
演示
Live On Coliru
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <random>
#include <iostream>
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
using boost::make_iterator_range;
int main() {
Graph g(23);
auto weight_distribution = std::bind(std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
}
打印例如
0 -> 0 weight 0 ROOT
15 -> 1 weight 64.6241
21 -> 2 weight 62.1609
1 -> 3 weight 69.207
5 -> 4 weight 71.9255
2 -> 5 weight 68.3983
14 -> 6 weight 66.6639
17 -> 7 weight 69.5045
20 -> 8 weight 78.9941
6 -> 9 weight 69.3287
4 -> 10 weight 62.7512
0 -> 11 weight 65.9305
15 -> 12 weight 70.2627
4 -> 13 weight 67.9708
22 -> 14 weight 73.3816
14 -> 15 weight 61.069
6 -> 16 weight 63.5795
5 -> 17 weight 66.0981
6 -> 18 weight 54.6061
14 -> 19 weight 73.9725
5 -> 20 weight 74.7002
0 -> 21 weight 71.8757
17 -> 22 weight 68.6378
Total path weight 1504.64