function tarjan(graph: Graph) {let index = 0; const stack: Node[] = []; const onStack = new Set<Node>();
const indexOf = new Map<Node, number>(), lowLink = new Map<Node, number>(); const components: Node[][] = [];
const visit = (node: Node) => {indexOf.set(node, index); lowLink.set(node, index); index++;
stack.push(node); onStack.add(node);
for (const next of graph.successors(node)) { if (!indexOf.has(next)) { visit(next); lowLink.set(node, Math.min(lowLink.get(node)!, lowLink.get(next)!)); }else if (onStack.has(next)) lowLink.set(node, Math.min(lowLink.get(node)!, indexOf.get(next)!));
}
if (lowLink.get(node) === indexOf.get(node)) {const component: Node[] = [];
let top: Node; do { top = stack.pop()!; onStack.delete(top); component.push(top); } while (top !== node);components.push(component);
}
};
for (const node of graph.nodes) if (!indexOf.has(node)) visit(node);
return components;
}
A is unvisited: start a depth-first search there.
Understanding Tarjan SCC
The idea
A strongly connected component is a set of nodes that can all reach each other. Tarjan finds them in a single depth-first search by giving every node an index in visit order and a low link: the smallest index reachable from it through its DFS subtree plus at most one back edge. Visited nodes stay on a stack until their component is complete.
When the search returns to a node whose low link still equals its own index, nothing below it reaches back above it, so it is the root of a component: everything on the stack down to it is popped as one component. The label under each node shows index / low link.
The four stages
Complexity
Versus its siblings
Pseudocode
TARJAN(graph)
VISIT(node): index[node] ← low[node] ← counter++; push node
for each successor: unvisited → VISIT it, low[node] ← min(low[node], low[successor]); on the stack → low[node] ← min(low[node], index[successor])
if low[node] = index[node]: pop the stack down to node, that is one component
VISIT every unvisited node
When to use
Pitfalls
History
Robert Tarjan published the algorithm in 1972 in the same paper that made depth-first search a first-class tool, alongside linear-time biconnectivity. It remains the reference SCC algorithm; Gabow's path-based variant from 2000 replaces low links with a second stack.