You can use a boost::filtered_graph
to dynamically filter the edges you don't want to cross. To this end you must first write an edge predicate to filter out null weighted edges.
Here is a possible implementation of the predicate:
template <typename EdgeWeightMap>
struct non_null_weight_edge {
non_null_weight_edge() {}
non_null_weight_edge(EdgeWeightMap const& map) : weight_map(map) {}
template <typename Edge>
bool operator()(Edge const& e) const {
return (boost::get(weight_map, e) != 0);
}
private:
EdgeWeightMap weight_map;
};
EdgeWeightMap
must be a ReadablePropertyMap
defining the weights for the edges.
Assuming you start with a graph looking like this:
// Just for clarity's sake while printing graph
struct VertexProperty {
std::string name;
};
struct EdgeProperty {
int weight; // Required
// Add whatever you want...
};
using RawGraph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
VertexProperty, EdgeProperty>;
You can instantiate a predicate like this:
RawGraph graph; // Populate it however you want...
auto weight_map = boost::get(graph, &EdgeProperty::weight);
auto predicate = non_null_weight_edge<decltype(weight_map)>(weight_map);
Now, we create the filtered graph to perform our BFS:
boost::filtered_graph<RawGraph, decltype(predicate)>(graph, predicate);
The next step is to record which vertices we will discover during the BFS, this is really simple as you only have to define the discover_vertex
part of the BFSVisitor
:
template <typename VertexSet>
struct VertexDetectorVisitor : boost::default_bfs_visitor {
VertexDetectorVisitor(VertexSet& output_vec) :
visited(output_vec) {}
template <typename Vertex, typename Graph>
void discover_vertex(Vertex const& v, Graph const& g) {
visited.insert(v);
}
private:
VertexSet& visited;
};
Putting all the pieces together leads you to something running like this live demo.