简体   繁体   English

助力图BFS忽略零权重边缘

[英]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. 我在从邻接列表有向图的构建中构建特定的BFS时遇到了一些麻烦。 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. 我建议使用带有动态集合“已删除”(已过滤)顶点或边的filtered_graph适配器

I have some samples on StackOverflow using this approach I think. 我认为使用这种方法在StackOverflow上有一些示例 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. 您可以使用boost::filtered_graph动态过滤您不想交叉的边缘。 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. EdgeWeightMap必须是ReadablePropertyMap用于定义边缘的权重。

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: 现在,我们创建过滤图以执行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 : 下一步是记录我们将在BFS中发现哪些顶点,这非常简单,因为您只需要定义BFSVisitordiscover_vertex部分:

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 . 将所有部分放在一起,您将获得像此实时演示一样运行的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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