Search code examples
c++c++11boost-graph

How can I get input edges of a given vertex on a directed graph?


I have a directed graph and I want to fetch the parent of a given vertex.

Say I have the graph 1 -> 2 -> 3, I hold the vertex 2 and I want to get vertex 1.

My vertex and graph definitions:

struct TreeVertex   {  int id = -1;  };

typedef boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::directedS,
    TreeVertex
    > tree_t;

An MVCE showing what I want to achieve (see online here):

int main() {
    tree_t tree;
    auto v1 = boost::add_vertex( tree );    
    auto v2 = boost::add_vertex( tree );    
    auto v3 = boost::add_vertex( tree );    
    boost::add_edge( v1, v2, tree );
    boost::add_edge( v2, v3, tree );

// attempt to get the input edge of v2
    auto pair_it_edge = boost::in_edges( v2, tree ); // FAILS TO BUILD  
    auto v = boost::source( *pair_it_edge.first ); // should be v1
}

Another answer suggests transforming the graph into a BidirectionalGraph but I need to keep it directed.

Question: Is this possible ? How can I get the incoming edge of v2, so that I can extract v1 ?


Solution

  • Without using a bidirectional graph, you will have to do a brute force search of all the nodes, looking for one that has vertex 2 as its child.

    #include <iostream>
    #include <boost/graph/adjacency_list.hpp>
    using namespace std;
       using namespace boost;
    
    struct TreeVertex   {  int id = -1;  };
    
    typedef boost::adjacency_list<
        boost::vecS,
        boost::vecS,
        boost::directedS,
        TreeVertex
        > tree_t;
    
        tree_t tree;
    
    
    int main() {
    
    
        auto v1 = boost::add_vertex( tree );    
        auto v2 = boost::add_vertex( tree );    
        auto v3 = boost::add_vertex( tree );    
        boost::add_edge( v1, v2, tree );
        boost::add_edge( v2, v3, tree );
    
        int looking_for = 2;
    
        typename graph_traits < tree_t >::out_edge_iterator ei, ei_end;
        for( int v = 0; v < num_edges( tree ); v++ )
        for (boost::tie(ei, ei_end) = out_edges(v, tree); ei != ei_end; ++ei) {
        auto source = boost::source ( *ei, tree );
        auto target = boost::target ( *ei, tree );
        if( target == looking_for )
            std::cout << "There is an edge from " << source <<  " to " << target << std::endl;
    
    // create an inverted edge tree to search for parents
    tree_t invtree;
    boost::add_edge( v2, v1, invtree );
    boost::add_edge( v1, v3, invtree );
    typename graph_traits < tree_t >::adjacency_iterator it, it_end;
    for (tie(it, it_end) = adjacent_vertices(v2, invtree ); it != it_end; ++it) 
    {
        std::cout << "There is an inv edge from " <<  v2
            << " to " << *it << std::endl;
    }
    
    
        return 0;
    }
    

    It may be worthwhile to create a temporary tree with inverted edges as a 'copy' of your graph to simplify the search for parents. Something like invtree at the end of the code posted.