Boost DFS how to save visited vertices?

2019-07-11 18:59发布

I'm looking at the solution here, which doesn't work for me (but read under the === line to actually see the current problem).

I tried:

boost::undirected_dfs(G, vertex(0,G), boost::visitor(vis)); 

but I get

error C2780: 'void boost::undirected_dfs(const Graph &,const boost::bgl_named_params<P,T,R> &)' : expects 2 arguments - 3 provided
error C2780: 'void boost::undirected_dfs(const Graph &,DFSVisitor,VertexColorMap,EdgeColorMap)' : expects 4 arguments - 3 provided

etc. I sort of get what the problem is (I need to pass it some named parameters, but I don't have any in my graph, I think. Also, I don't get what the deal with the color maps is, at all.

=============================================================================

My graph is defined:

typedef boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, boost::no_property, EdgeInfoProperty > Graph;
typedef Graph::edge_descriptor Edge;
typedef Graph::vertex_descriptor Vertex;

All I want is to do DFS, at least for now.

So I changed it to boost::depth_first_search, and it seems to work.

I have (note the lack of const for void discover_vertex vs. the solution linked above):

class MyVisitor : public boost::default_dfs_visitor {
public:
    void discover_vertex(Vertex v, const Graph& g)  { //note the lack of const
        if(boost::in_degree(v,g)!=0){ //only print the vertices in the connected component (I already did MCC and removed edges so all the extra vertices are isolated)
            std::cerr << v << std::endl;
            vv.push_back(v);
        }
        return;
    }
    std::vector<Vertex> GetVector() const  { return vv; }
private: 
    std::vector<Vertex> vv;
};

If I leave const there I get error C2663: 'std::vector<_Ty>::push_back' : 2 overloads have no legal conversion for 'this' pointer with [ _Ty=size_t ].

Now, this works fine or at least it prints out the right visited vertices, in the right order:

MyVisitor vis;
boost::depth_first_search(G, boost::visitor(vis)); 

But when I do:

std::vector<Vertex> vctr = vis.GetVector();
std::cout<<vctr.size();

the size is zero, because my vv doesn't change...

So, how can I get the appropriate class behavior when the class is used as an argument to boost::visitor? (I'm not even sure this is the appropriate question). I need to be able to change EdgeInfoProperty based on which nodes were visited before (or rather based on which vertex is the parent of the current vertex in the DFS traversal, so this would probably just be a first step towards that).

1条回答
看我几分像从前
2楼-- · 2019-07-11 19:35

The visitor is passed by value, so you need to share the vector it holds with the instance of MyVisitor copied into the function call.

Try this:

class MyVisitor : public boost::default_dfs_visitor {
public:
    MyVisitor(): vv(new std::vector<Vertex>()){}

    void discover_vertex(Vertex v, const Graph& g)  { //note the lack of const
        if(boost::in_degree(v,g)!=0){ //only print the vertices in the connected component (I already did MCC and removed edges so all the extra vertices are isolated)
            std::cerr << v << std::endl;
            vv->push_back(v);
        }
        return;
    }
    std::vector<Vertex>& GetVector() const  { return *vv; }
private: 
    boost::shared_ptr< std::vector<Vertex> > vv;
};
查看更多
登录 后发表回答