8

I need to find an algorithm for finding all the roots in a directed graph, in O(n+m).

I have an algorithm for finding a single root:

  1. Run DFS(v) on some v in V. If the result is a single spanning tree, then v is a root. Otherwise, the result is a forest of trees. Then:
  2. Run DFS(u) on the root of the last tree. If the result is a single spanning tree, then u is a root. Else, there are no roots in the graph.

Now if I want to find all the roots, is the best way to just run the above algorithm O(n) times, on a different vertex in the last tree every time ? Assuming I found a root, if another root exists then it must be on the last tree, then is it O(n+m) if I continue to run the above algorithm until receiving "no root exists" or until going over all vertices ?

Thanks in advance !

amitooshacham
  • 614
  • 1
  • 7
  • 16
  • look up topological sort. Still your question does not make a look of sense. The term `root` is only defined for a root. I assume you need all vertices with no incoming edge? – Ivaylo Strandjev Nov 13 '13 at 10:01
  • @IvayloStrandjev ... which are called ["source vertices"](http://en.wikipedia.org/wiki/Vertex_(graph_theory)). – Bernhard Barker Nov 13 '13 at 10:09
  • Assuming you have found a root correctly, you may then find vertices that have a directed path to that root. All such vertices shall be roots themselves. Or you can reverse the direction of all edges and conduct a DFS or BFS from that found root. All the vertices encountered shall be roots themselves. – Abhishek Bansal Nov 13 '13 at 10:21
  • 1
    @amitooshacham As I said, IMO if you reverse the direction of all edges and conduct a DFS or BFS from the root, then you can get all the new roots. – Abhishek Bansal Nov 13 '13 at 10:26
  • Is reversing the direction of all edges O(n) ? – amitooshacham Nov 13 '13 at 10:30
  • 1
    Yes, reversing all edges is O(n) where n is the number of edges. – Abhishek Bansal Nov 13 '13 at 10:32
  • @AbhishekBansal We were asked to give an algorithm in O(|V|+|E|), however the first algorithm I described is O(|E|) and your algorithm is O(|E|) which gives me O(2|E|) = O(|E|). What am I missing ? – amitooshacham Nov 13 '13 at 10:50
  • One small edit for my last comment: Look up topological sort. Still your question does not make a look of sense. The term root is only defined for a **tree**. I assume you need all vertices with no incoming edge? – Ivaylo Strandjev Nov 13 '13 at 11:05
  • @IvayloStrandjev we were taught that in a graph G, a root is a vertex in which any other vertex is reachable from it. – amitooshacham Nov 13 '13 at 11:12
  • @amitooshacham if E >> V, then O(V+E) ~ O(E) (our solution), and if V >> E, then O(V+E) > O(E) which means our solution has achieved better complexity. – Abhishek Bansal Nov 13 '13 at 11:27

2 Answers2

5

Two approaches:

  1. Reverse the graph and calculate DFS-loop() and note the vertices which have no outgoing edges (like Abhishek said).

  2. More efficient - Run DFS-loop() on the graph and keep track of vertices with no incoming edges using a true, false table.

Method 1 takes twice as long in the worst case.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Vikram Bhat
  • 6,106
  • 3
  • 20
  • 19
  • can you elaborate on the second method? – Abhishek Bansal Nov 13 '13 at 16:31
  • But as per OP's definition, a root can have incoming edges also. In fact if there is a node without any incoming edge, then that node is the single only root of the tree because it cannot be traversed from any other 'possible root node'. – Abhishek Bansal Nov 13 '13 at 17:16
  • there can be more than one root in graph which have no incoming edges – Vikram Bhat Nov 13 '13 at 18:00
  • if you mean root can have incoming edges than it is part of SCC with no incoming edges . So we use Kasaraju's algorthim for SCC's to reduce the graph to one on which 2.> can work. – Vikram Bhat Nov 13 '13 at 18:58
2

First you should find all strongly connected components in graph. To build it in leaner time you can use Kosaraju's algorithm or Tarjan's algorithm. All root should be located in one such component. Next you find strongly connected components without incoming edges to it. If you have more then one such component, graph has no root vertices. In you has only one component, you should check that you can reach others component from it, in this case this components contains all root in graph.

Old variant.

You should calculate the number of incoming edges to vertex, this can be done in O(m). All vertices with zero number of incoming edges will be a root of the graph, for this you will need O(n) time.

Alexander Kuznetsov
  • 3,062
  • 2
  • 25
  • 29
  • 1
    I think you are mixing up "root" and "source". Unless I'm mistaken, a root is a node from which each other node can be reached via directed edges. The root might itself have incoming edges, and definitely not each node with no such edges would be a root. – tobias_k Nov 13 '13 at 09:51