// A C++ program to find strongly connected components in a // given directed graph using Tarjan's algorithm (single // DFS) #include <algorithm> #include <iostream> #include <list> #include <stack> #include <vector> #define NIL -1 using namespace std; // A class that represents a directed graph class Graph { int V; // No. of vertices list<int>* adj; // A dynamic array of adjacency lists // A Recursive DFS based function used by SCC() void SCCUtil(int u, int disc[], int low[], stack<int>* st, bool stackMember[]); public: Graph(int V); // Constructor void addEdge(int v, int w); // function to add an edge to the graph void SCC(); // prints strongly connected components }; Graph::Graph(int V) { this->V = V; adj = new list<int>[V]; } void Graph::addEdge(int v, int w) { adj[v].push_back(w); } // A recursive function that finds and prints strongly // connected components using DFS traversal void 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' low[u] = min(low[u], low[v]); } // Update low value of 'u' only if 'v' is still in // stack (i.e., it's a back edge, not a cross edge) 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); // Free allocated memory delete[] disc; delete[] low; delete[] stackMember; delete st; } // Driver program to test above function int main() { cout << "\nSCCs in first graph \n"; Graph g1(5); g1.addEdge(1, 0); g1.addEdge(0, 2); g1.addEdge(2, 1); g1.addEdge(0, 3); g1.addEdge(3, 4); g1.SCC(); cout << "\nSCCs in second graph \n"; Graph g2(4); g2.addEdge(0, 1); g2.addEdge(1, 2); g2.addEdge(2, 3); g2.SCC(); cout << "\nSCCs in third graph \n"; Graph g3(7); g3.addEdge(0, 1); g3.addEdge(1, 2); g3.addEdge(2, 0); g3.addEdge(1, 3); g3.addEdge(1, 4); g3.addEdge(1, 6); g3.addEdge(3, 5); g3.addEdge(4, 5); g3.SCC(); cout << "\nSCCs in fourth graph \n"; Graph g4(11); g4.addEdge(0, 1); g4.addEdge(0, 3); g4.addEdge(1, 2); g4.addEdge(1, 4); g4.addEdge(2, 0); g4.addEdge(2, 6); g4.addEdge(3, 2); g4.addEdge(4, 5); g4.addEdge(4, 6); g4.addEdge(5, 6); g4.addEdge(5, 7); g4.addEdge(5, 8); g4.addEdge(5, 9); g4.addEdge(6, 4); g4.addEdge(7, 9); g4.addEdge(8, 9); g4.addEdge(9, 8); g4.SCC(); cout << "\nSCCs in fifth graph \n"; Graph g5(5); g5.addEdge(0, 1); g5.addEdge(1, 2); g5.addEdge(2, 3); g5.addEdge(2, 4); g5.addEdge(3, 0); g5.addEdge(4, 2); g5.SCC(); return 0; }