You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Boost Graph Library的BFS遍历创建独立ColorMap?

问题描述

我用(x,y,z)坐标标识3D晶格的每个单元格,单元格属性存在Cell类中。将Cell作为Boost Graph Library(BGL)的顶点对象,先构造空图,遍历所有单元格插入顶点,再根据邻域单元格的特定条件构建边。

需求是统计孤立连通单元格(簇)的数量,这是典型的广度优先搜索(BFS)场景,计划用BGL工具实现:遍历每个单元格,若未被访问且存在边,则遍历所有连通单元格,标记为同一簇并分配簇ID。

根据BGL文档,处理不连通组件需要多次BFS时,应使用breadth_first_visit()函数并自行初始化颜色。我选择了第二个重载版本:

template <class IncidenceGraph, class Buffer, class BFSVisitor, class ColorMap>
void breadth_first_visit
  (const IncidenceGraph& g,
   typename graph_traits<IncidenceGraph>::vertex_descriptor s,
   Buffer& Q, BFSVisitor vis, ColorMap color)

不想在Cell类中添加颜色属性,于是用std::map存储顶点描述符和颜色值的映射作为独立ColorMap:

struct Test002Vertex;
using Test002Graph=boost::adjacency_list<boost::vecS, boost::listS,boost::undirectedS,Test002Vertex>;
using Test002GraphTraits=boost::graph_traits<Test002Graph>;
// same as Test002Graph::vertex_descriptor
using Test002VertexDescriptor=Test002GraphTraits::vertex_descriptor;

// implement Buffer concept
template<typename T,typename Container=std::deque<T>>
class buffer { ... };

// ...

// user defined colour map
std::map<Test002VertexDescriptor,boost::default_color_type> colour_map;
for(auto const &v:graph.vertex_set())
{
  colour_map[v]=boost::default_color_type::white_color;
}

buffer<Test002VertexDescriptor> buffer;

breadth_first_visit(graph,*graph.vertex_set().begin(),buffer,Test002_BFS_Visitor<Test002Graph>(),colour_map);

图的构造代码可正常运行,邻接表打印验证正确,但调用breadth_first_visit()时编译失败。排查发现ColorMap需符合Boost Property Map规范,求解决方案。

感谢@sehe提供的自定义ColorMap示例。

解决方案

BGL的breadth_first_visit()要求ColorMap必须符合Property Map概念,直接传入std::map无法满足要求,因为BGL需要通过Property Map的标准接口(如get()、put()函数)来访问和修改值。可以通过以下方式解决:

方法1:用boost::associative_property_map适配std::map

Boost提供了associative_property_map模板,专门用来适配std::map这类关联容器,使其符合Property Map规范。修改代码如下:

#include <boost/property_map/associative_property_map.hpp>

// ...

std::map<Test002VertexDescriptor, boost::default_color_type> colour_map;
for(auto const &v : graph.vertex_set()) {
  colour_map[v] = boost::default_color_type::white_color;
}

// 将std::map包装为符合规范的Property Map
boost::associative_property_map<std::map<Test002VertexDescriptor, boost::default_color_type>> color_map_wrapper(colour_map);

buffer<Test002VertexDescriptor> buffer;

// 传入包装后的Property Map
breadth_first_visit(graph, *graph.vertex_set().begin(), buffer, Test002_BFS_Visitor<Test002Graph>(), color_map_wrapper);

方法2:用boost::vector_property_map(适用于顶点描述符为整数的场景)

如果你的顶点存储方式是vecS(此时顶点描述符为整数类型),可以使用vector_property_map,它的性能比std::map更优:

#include <boost/property_map/vector_property_map.hpp>

// ...

// 获取顶点总数
size_t vertex_count = boost::num_vertices(graph);
boost::vector_property_map<boost::default_color_type> color_map(vertex_count);

// 初始化所有顶点颜色为white_color
boost::fill(color_map, boost::default_color_type::white_color);

buffer<Test002VertexDescriptor> buffer;

breadth_first_visit(graph, *graph.vertex_set().begin(), buffer, Test002_BFS_Visitor<Test002Graph>(), color_map);

简化方案:直接使用connected_components()统计连通分量

如果只是为了统计连通簇的数量,无需手动实现多次BFS,BGL提供了现成的connected_components()函数,代码更简洁:

#include <boost/graph/connected_components.hpp>

// ...

std::vector<int> component_ids(boost::num_vertices(graph));
int cluster_count = boost::connected_components(graph, &component_ids[0]);

// cluster_count即为所求的连通簇数量

内容的提问来源于stack exchange,提问作者Victor Tsang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 05:14:51