我试图在无向图中找到属于任何循环一部分的所有边。使用Boost的depth_first_search和我对back edges的理解,我不明白为什么在示例Graph中为两个边调用back_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;
}
答案 0 :(得分:2)
由于图表是无向的,因此任何树边缘也都是后边缘。 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));
}