function createGraph(nodes, edges) { const result = nodes.reduce((acc, el) => { acc[el] = []; return acc; }, {}); for (let edge of edges) { result[edge[0]].push(edge[1]); } return result; } function dfsWithMark(graph, currentNode) { const visited = {}; const marks = {}; let step = 1; const pathForReverse = []; const inner = function (node) { let nextEl = graph[node].find(el => !visited[el]); if (nextEl !== undefined) { visited[nextEl] = 1; pathForReverse.push(node); } else { nextEl = pathForReverse.pop(); } if (nextEl === undefined) return; marks[nextEl] = ++step; inner(nextEl); } inner(currentNode); return marks; } function reverseGraph(graph) { const result = nodes.reduce((acc, el) => { acc[el] = []; return acc; }, {}) for (let node in graph) { for (let child of graph[node]) { if (!result[child]) { result[child] = []; } result[child].push(node); } } return result; } function kosaraju(nodes, edges) { const graph = createGraph(nodes, edges); const reversedGraph = reverseGraph(graph); const marks = dfsWithMark(graph, nodes[0]); const sortedMarks = Object.entries(marks).sort((a, b) => b[1] - a[1]); const stronglyConnectedComponents = []; let groupIndex = 0; let next = undefined; let visited = {}; for (let node of sortedMarks) { if (visited[node[0]]) continue; visited[node[0]] = 1; stronglyConnectedComponents[groupIndex] = [node[0]]; next = reversedGraph[node[0]].find(el => !visited[el]); if (next === undefined) { groupIndex++; continue; } while (next !== undefined) { visited[next] = 1; stronglyConnectedComponents[groupIndex].push(next); next = reversedGraph[next].find(el => !visited[el]) } groupIndex++; } return stronglyConnectedComponents; } const nodes = [0, 1, 2, 3, 4, 5, 6, 7, 20]; const edges = [ [0, 1], [1, 2], [1, 3], [3, 1], [3, 4], [4, 20], [4, 5], [5, 6], [6, 3], [6, 7], ]; const r = kosaraju(nodes, edges); console.log(r);