代码之家  ›  专栏  ›  技术社区  ›  mb21

提升DFS后退(_E)

  •  3
  • mb21  · 技术社区  · 12 年前

    我试图找到无向图中任何循环的一部分的所有边。使用Boost depth_first_search 以及我对 back edges ,我不明白为什么 back_edge 方法是为不包含任何循环的示例Graph中的两条边调用的。

    #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;
    }
    
    1 回复  |  直到 12 年前
        1
  •  2
  •   sehe    12 年前

    由于你的图是无向的,所以任何树的边都是后边。这个 documentation for DFSVisitor 没有不提到这一点。

    对于无向图,树边和后边之间存在一些模糊性,因为边(u,v)和(v,u)是同一条边,但两者都是 tree_edge() back_edge() 将调用函数。

    解决这种模糊性的一种方法是记录树的边缘,然后忽略已经标记为树边缘的后边缘。记录树边缘的一种简单方法是在tree_edge事件点记录前置。

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

    #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));
    }