Graph algorithm to collect all edges which are on any path between two nodes

1.2k views Asked by At

I need to find all edges which are on any path between two nodes [src, dest] in a directed graph.

Means that each edge (from base to head) has to satisfy:

  • there is a path from src to base
  • there is a path from head to dest

I could collect all edges which are connected to src and collect all edges which are connected in inverse direction to dest and compute the intersection of them.

But there has to be an algorithm, right? (Don't know if there can be a more efficient) So I am searching for the name, or clever solutions to solve it with existing algorithms.

2

There are 2 answers

0
thi gg On BEST ANSWER

To get an overall result I'll report what I did.

I implemented the in the question mentioned algorithm. (Lets call it thigg's algorithm, because noone mentioned a name)

Thigg's algorithm:

for each node in the graph:
     if there is a path from src to this node 
        and a path from this node to dest, 
       push node to the result list.

As mentioned by Edward Doolittle in his answer the graph can be optimized before by identifying Strongly-Connected-Components and reducing them to one node. This would reduce the effort of the algorithm on each run.

I implemented thiggs algorithm with the Boost-Graph-Library (without SCC optimization) where a is the source and b the destination vertex:

I used a breadth first search to get a list of all vertexes which are reachable by a:

boost::breadth_first_search(graph, a, visitor(vis));

Where vis is a custom visitor which puts all the visited vertexes to a list. Then it reverts the graph to get all vertexes which can reach b

boost::breadth_first_search(boost::make_reverse_graph(graph), b, visitor(vis));

And finally computes the intersection:

std::set_intersection(froma.begin(),froma.end(),fromb.begin(),fromb.end(),back_inserter(inters));

Note that your graph has to be bidirectional in order to use make_reverse_graph.

The algorithm also works for edges as mentioned in the question.

3
Edward Doolittle On

If you are only answering your question once, the individuals who commented on your question are correct: your proposed solution is correct and fast. However, if you are answering your question multiple times for different src and dest in a fixed graph, there is a way to "index" the information to speed queries.

Tarjan's algorithm will decompose a directed graph into strongly connected components (SCCs) in O(V+E) time. A strongly connected component is a set of vertices which are all mutually reachable by following the digraph.

The set of strongly connected components will themselves form a directed acyclic graph (DAG).

If src and dest are in the same SCC, then the set of edges you are looking for is exactly the set of edges in the SCC.

If the SCC containing dest is unreachable from the SCC containing src in the DAG, there is no path from src to dest, so the set of edges you are looking for is empty.

If the SCC containing dest is reachable from the SCC containing src, you need to find all paths from src SCC to dest SCC in the DAG, which is a very simple dynamic programming problem. Then the set of edges you want is the set of edges in all the SCCs between src SCC and dest SCC, plus the "pullbacks" of the edges of the relevant paths in the DAG to the edges in the original graph.

It may sound confusing, but the diagram on the Wikipedia page may help to clarify.