简体   繁体   中英

Boost graph BFS that ignores zero weight edges

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:

  1. Start at a source
  2. Only cross edges with positive edge weight.
  3. Record vertices encountered (to some array).
  4. Delete Nodes from the original graph as they are used up.

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?

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM