You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.8 KiB
80 lines
2.8 KiB
// deep first search with both order low for pre, lim for post
|
|
const dfsBothOrder = (g) => {
|
|
const result = {};
|
|
let lim = 0;
|
|
const dfs = (v) => {
|
|
const low = lim;
|
|
g.getChildren(v).forEach((n) => dfs(n.id));
|
|
result[v] = { low, lim: lim++ };
|
|
};
|
|
g.getRoots().forEach((n) => dfs(n.id));
|
|
return result;
|
|
};
|
|
// Find a path from v to w through the lowest common ancestor (LCA). Return the
|
|
// full path and the LCA.
|
|
const findPath = (g, postorderNums, v, w) => {
|
|
var _a, _b;
|
|
const vPath = [];
|
|
const wPath = [];
|
|
const low = Math.min(postorderNums[v].low, postorderNums[w].low);
|
|
const lim = Math.max(postorderNums[v].lim, postorderNums[w].lim);
|
|
let parent;
|
|
let lca;
|
|
// Traverse up from v to find the LCA
|
|
parent = v;
|
|
do {
|
|
parent = (_a = g.getParent(parent)) === null || _a === void 0 ? void 0 : _a.id;
|
|
vPath.push(parent);
|
|
} while (parent &&
|
|
(postorderNums[parent].low > low || lim > postorderNums[parent].lim));
|
|
lca = parent;
|
|
// Traverse from w to LCA
|
|
parent = w;
|
|
while (parent && parent !== lca) {
|
|
wPath.push(parent);
|
|
parent = (_b = g.getParent(parent)) === null || _b === void 0 ? void 0 : _b.id;
|
|
}
|
|
return { lca, path: vPath.concat(wPath.reverse()) };
|
|
};
|
|
export const parentDummyChains = (g, dummyChains) => {
|
|
const postorderNums = dfsBothOrder(g);
|
|
dummyChains.forEach((startV) => {
|
|
var _a, _b;
|
|
let v = startV;
|
|
let node = g.getNode(v);
|
|
const originalEdge = node.data.originalEdge;
|
|
if (!originalEdge)
|
|
return;
|
|
const pathData = findPath(g, postorderNums, originalEdge.source, originalEdge.target);
|
|
const path = pathData.path;
|
|
const lca = pathData.lca;
|
|
let pathIdx = 0;
|
|
let pathV = path[pathIdx];
|
|
let ascending = true;
|
|
while (v !== originalEdge.target) {
|
|
node = g.getNode(v);
|
|
if (ascending) {
|
|
while (pathV !== lca &&
|
|
((_a = g.getNode(pathV)) === null || _a === void 0 ? void 0 : _a.data.maxRank) < node.data.rank) {
|
|
pathIdx++;
|
|
pathV = path[pathIdx];
|
|
}
|
|
if (pathV === lca) {
|
|
ascending = false;
|
|
}
|
|
}
|
|
if (!ascending) {
|
|
while (pathIdx < path.length - 1 &&
|
|
((_b = g.getNode(path[pathIdx + 1])) === null || _b === void 0 ? void 0 : _b.data.minRank) <= node.data.rank) {
|
|
pathIdx++;
|
|
}
|
|
pathV = path[pathIdx];
|
|
}
|
|
if (g.hasNode(pathV)) {
|
|
g.setParent(v, pathV);
|
|
}
|
|
v = g.getSuccessors(v)[0].id;
|
|
}
|
|
});
|
|
};
|
|
//# sourceMappingURL=parent-dummy-chains.js.map
|