Tarjan's Algorithm to find Strongly Connected Components - GeeksforGeeks
A directed graph is strongly connected if there is a path between all pairs of vertices. A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. For example, there are 3 SCCs in the following graph.
Read full article from Tarjan's Algorithm to find Strongly Connected Components - GeeksforGeeks
A directed graph is strongly connected if there is a path between all pairs of vertices. A strongly connected component (SCC) of a directed graph is a maximal strongly connected subgraph. For example, there are 3 SCCs in the following graph.
Kosaraju’s algorithm for strongly connected components. The previously discussed algorithm requires two DFS traversals of a Graph. In this post, Tarjan’s algorithm is discussed that requires only one DFS traversal.
Tarjan Algorithm is based on following facts:
1. DFS search produces a DFS tree/forest
2. Strongly Connected Components form subtrees of the DFS tree.
3. If we can find head of such subtrees, we can print/store all the nodes in that subtree (including head) and that will be one SCC.
4. There is no back edge from one SCC to another (There can be cross edges, but cross edges will not be used while processing the graph).
1. DFS search produces a DFS tree/forest
2. Strongly Connected Components form subtrees of the DFS tree.
3. If we can find head of such subtrees, we can print/store all the nodes in that subtree (including head) and that will be one SCC.
4. There is no back edge from one SCC to another (There can be cross edges, but cross edges will not be used while processing the graph).
To find head of a SCC, we calculate desc and low array (as done for articulation point, bridge,biconnected component). As discussed in the previous posts, low[u] indicates earliest visited vertex (the vertex with minimum discovery time) that can be reached from subtree rooted with u. A node u is head if disc[u] = low[u].
// A recursive function that finds and prints strongly connected// components using DFS traversal// u --> The vertex to be visited next// disc[] --> Stores discovery times of visited vertices// low[] -- >> earliest visited vertex (the vertex with minimum// discovery time) that can be reached from subtree// rooted with current vertex// *st -- >> To store all the connected ancestors (could be part// of SCC)// stackMember[] --> bit/index array for faster check whether// a node is in stackvoid Graph::SCCUtil(int u, int disc[], int low[], stack<int> *st, bool stackMember[]){ // A static variable is used for simplicity, we can avoid use // of static variable by passing a pointer. static int time = 0; // Initialize discovery time and low value disc[u] = low[u] = ++time; st->push(u); stackMember[u] = true; // Go through all vertices adjacent to this list<int>::iterator i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { int v = *i; // v is current adjacent of 'u' // If v is not visited yet, then recur for it if (disc[v] == -1) { SCCUtil(v, disc, low, st, stackMember); // Check if the subtree rooted with 'v' has a // connection to one of the ancestors of 'u' // Case 1 (per above discussion on Disc and Low value) low[u] = min(low[u], low[v]); } // Update low value of 'u' only of 'v' is still in stack // (i.e. it's a back edge, not cross edge). // Case 2 (per above discussion on Disc and Low value) else if (stackMember[v] == true) low[u] = min(low[u], disc[v]); } // head node found, pop the stack and print an SCC int w = 0; // To store stack extracted vertices if (low[u] == disc[u]) { while (st->top() != u) { w = (int) st->top(); cout << w << " "; stackMember[w] = false; st->pop(); } w = (int) st->top(); cout << w << "\n"; stackMember[w] = false; st->pop(); }}// The function to do DFS traversal. It uses SCCUtil()void Graph::SCC(){ int *disc = new int[V]; int *low = new int[V]; bool *stackMember = new bool[V]; stack<int> *st = new stack<int>(); // Initialize disc and low, and stackMember arrays for (int i = 0; i < V; i++) { disc[i] = NIL; low[i] = NIL; stackMember[i] = false; } // Call the recursive helper function to find strongly // connected components in DFS tree with vertex 'i' for (int i = 0; i < V; i++) if (disc[i] == NIL) SCCUtil(i, disc, low, st, stackMember);}