48 lines
962 B
JavaScript
48 lines
962 B
JavaScript
|
var _ = require("../lodash");
|
||
|
|
||
|
module.exports = tarjan;
|
||
|
|
||
|
function tarjan(g) {
|
||
|
var index = 0;
|
||
|
var stack = [];
|
||
|
var visited = {}; // node id -> { onStack, lowlink, index }
|
||
|
var results = [];
|
||
|
|
||
|
function dfs(v) {
|
||
|
var entry = visited[v] = {
|
||
|
onStack: true,
|
||
|
lowlink: index,
|
||
|
index: index++
|
||
|
};
|
||
|
stack.push(v);
|
||
|
|
||
|
g.successors(v).forEach(function(w) {
|
||
|
if (!_.has(visited, w)) {
|
||
|
dfs(w);
|
||
|
entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
|
||
|
} else if (visited[w].onStack) {
|
||
|
entry.lowlink = Math.min(entry.lowlink, visited[w].index);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
if (entry.lowlink === entry.index) {
|
||
|
var cmpt = [];
|
||
|
var w;
|
||
|
do {
|
||
|
w = stack.pop();
|
||
|
visited[w].onStack = false;
|
||
|
cmpt.push(w);
|
||
|
} while (v !== w);
|
||
|
results.push(cmpt);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
g.nodes().forEach(function(v) {
|
||
|
if (!_.has(visited, v)) {
|
||
|
dfs(v);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return results;
|
||
|
}
|