#define UNVISITED -1
int depth, num_scc;
vi num, lo, stk, vis;
vvi g;
// Tarjan's algorithm to find SCC's of directed graph; O(V+E).
// --> commonly used for pre-processing to contract digraph to DAG
void scc(int u) {
lo[u] = num[u] = depth++; // lo[u] <= num[u]
// push 'u' onto stack, and track explored vertices with 'vis'
stk.push_back(u);
vis[u] = 1;
for (auto &v : g[u]) {
if (num[v] == UNVISITED)
scc(v); // this part is amortized O(V)
// Condition to update:
if (vis[v])
lo[u] = min(lo[u], lo[v]);
}
// if root, i.e. start of an SCC
// Since only visited vertices may update lo[u], and initally we set lo[u] =
// num[u], then if lo[u] == num[u], we know 'u' is the root of this SCC. To
// access the members of this SCC, pop from our "stack" (i.e. 'stk', as
// vector), up to (and including) root 'u'.
if (lo[u] == num[u]) {
cout << "SCC #" << ++num_scc << ":";
for (;;) {
int v = stk.back();
stk.pop_back();
vis[v] = 0;
cout << " \n"[u == v] << v;
if (u == v)
break;
}
}
}
int main() {
// Number of vertices
int V;
V = 10;
// Build adjacency list
g.assign(V, vi());
// ...
depth = num_scc = 0;
num.assign(V, UNVISITED);
lo.assign(V, 0);
vis.assign(V, 0);
REP(i, V) {
if (num[i] == UNVISITED) {
scc(i);
}
}
return 0;
}