Boost 后缘增压

Boost 后缘增压,boost,boost-graph,Boost,Boost Graph,我试图找到无向图中任何循环的所有边。使用Boost和我对的理解,我不明白为什么在不包含任何循环的示例图中为两条边调用back\u edge方法 #include <boost/config.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/depth_first_search.hpp> using namespace std; using namespace boost;

我试图找到无向图中任何循环的所有边。使用Boost和我对的理解,我不明白为什么在不包含任何循环的示例图中为两条边调用
back\u edge
方法

#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>

using namespace std;
using namespace boost;

typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> > Graph;
typedef graph_traits<Graph>::edge_descriptor Edge;

class MyVisitor : public default_dfs_visitor {
    public: void back_edge(Edge e, const Graph& g) const {
        // should only be called when cycle found, right?
        cerr << "back_edge " << e << endl;
        return;
    }
};

int main() {
    Graph g;
    add_edge(0, 1, g);
    add_edge(0, 2, g);

    MyVisitor vis;
    depth_first_search(g, visitor(vis));
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
使用名称空间boost;
typedef邻接列表图;
typedef graph_traits::edge_描述符edge;
类MyVisitor:公共默认\u dfs\u访问者{
public:void back_edge(edge e、const Graph&g)const{
//应该只在找到循环时调用,对吗?

cerr因为你的图是无向的,所以任何树的边都是后边

对于无向图,由于边(u,v)和(v,u)是同一条边,因此树边和后边之间存在一些模糊性,但将调用
树边()
后边()
函数

解决此歧义的一种方法是记录树边,然后忽略已标记为树边的后边。记录树边的一种简单方法是在树边事件点记录前导

以最直接的方式实现这一点:

#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>

namespace {
    using namespace boost;

    typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> > Graph;
    typedef graph_traits<Graph>::edge_descriptor Edge;
    typedef std::set<Edge> EdgeSet;
}

struct MyVisitor : default_dfs_visitor {
    MyVisitor(EdgeSet& tree_edges) : tree_edges(tree_edges) {}

    void tree_edge(Edge e, const Graph& g) const {
        std::cerr << "tree_edge " << e << std::endl;
        tree_edges.insert(e);
    }
    void back_edge(Edge e, const Graph& g) const {
        if (tree_edges.find(e) == tree_edges.end())
            std::cerr << "back_edge " << e << std::endl;
    }

  private: 
    EdgeSet& tree_edges;
};

int main() {
    Graph g;
    add_edge(0, 1, g);
    add_edge(0, 2, g);

    std::set<Edge> tree_edges;
    MyVisitor vis(tree_edges);

    depth_first_search(g, visitor(vis));
}
#包括
#包括
#包括
名称空间{
使用名称空间boost;
typedef邻接列表图;
typedef graph_traits::edge_描述符edge;
typedef std::设置边缘集;
}
结构MyVisitor:默认\u dfs\u访问者{
MyVisitor(边集和树边):树边(树边){}
空树_边(边e、常数图和g)常数{

std::cerr在这个例子中,我们如何
记录前一个事件
在后一个事件上?@Bruce我认为把它作为一个新问题发布更有用我发了这个帖子: