"use strict"; module.exports = tarjan; // Adapted from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm#The_algorithm_in_pseudocode function tarjan(graph) { const indices = new Map(); const lowlinks = new Map(); const onStack = new Set(); const stack = []; const scc = []; let idx = 0; function strongConnect(v) { indices.set(v, idx); lowlinks.set(v, idx); idx++; stack.push(v); onStack.add(v); const deps = graph.get(v); for (const dep of deps) { if (!indices.has(dep)) { strongConnect(dep); lowlinks.set(v, Math.min(lowlinks.get(v), lowlinks.get(dep))); } else if (onStack.has(dep)) { lowlinks.set(v, Math.min(lowlinks.get(v), indices.get(dep))); } } if (lowlinks.get(v) === indices.get(v)) { const vertices = new Set(); let w = null; while (v !== w) { w = stack.pop(); onStack.delete(w); vertices.add(w); } scc.push(vertices); } } for (const v of graph.keys()) { if (!indices.has(v)) { strongConnect(v); } } return scc; }