Reputation: 21
I am having a bit of trouble constructing a specific BFS in boost from an adjacency list directed graph. Ideally, I would like it to:
Realizing that it may not be possible for a visitor to do all of these things at once, what is the best way to do this?
Upvotes: 2
Views: 248
Reputation: 6086
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.
Upvotes: 3
Reputation: 393457
I'd suggest using a filtered_graph
adaptor with a dynamic set of "deleted" (filtered) vertices or edges.
I have some samples on StackOverflow using this approach I think. In absense of sample code on your side, I'll let you find those and see how you fare.
Upvotes: 3