File size: 1,939 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
let tarjanStronglyConnected = function() {
let eles = this;
let nodes = {};
let index = 0;
let components = [];
let stack = [];
let cut = eles.spawn(eles);
const stronglyConnectedSearch = sourceNodeId => {
stack.push(sourceNodeId);
nodes[sourceNodeId] = {
index : index,
low : index++,
explored : false
};
let connectedEdges = eles.getElementById(sourceNodeId)
.connectedEdges()
.intersection(eles);
connectedEdges.forEach(edge => {
let targetNodeId = edge.target().id();
if (targetNodeId !== sourceNodeId) {
if (!(targetNodeId in nodes)) {
stronglyConnectedSearch(targetNodeId);
}
if (!(nodes[targetNodeId].explored)) {
nodes[sourceNodeId].low = Math.min(nodes[sourceNodeId].low,
nodes[targetNodeId].low);
}
}
});
if (nodes[sourceNodeId].index === nodes[sourceNodeId].low) {
let componentNodes = eles.spawn();
for (;;) {
const nodeId = stack.pop();
componentNodes.merge(eles.getElementById(nodeId));
nodes[nodeId].low = nodes[sourceNodeId].index;
nodes[nodeId].explored = true;
if (nodeId === sourceNodeId) {
break;
}
}
let componentEdges = componentNodes.edgesWith(componentNodes);
let component = componentNodes.merge(componentEdges);
components.push(component);
cut = cut.difference(component);
}
};
eles.forEach(ele => {
if (ele.isNode()) {
let nodeId = ele.id();
if (!(nodeId in nodes)) {
stronglyConnectedSearch(nodeId);
}
}
});
return {
cut,
components
};
};
export default {
tarjanStronglyConnected,
tsc: tarjanStronglyConnected,
tscc: tarjanStronglyConnected,
tarjanStronglyConnectedComponents: tarjanStronglyConnected
};
|