| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- import _ from 'lodash'
- function parentDummyChains (g) {
- const postorderNums = postorder(g)
- _.forEach(g.graph().dummyChains, function (v) {
- let node = g.node(v)
- const edgeObj = node.edgeObj
- const pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w)
- const path = pathData.path
- const lca = pathData.lca
- let pathIdx = 0
- let pathV = path[pathIdx]
- let ascending = true
- while (v !== edgeObj.w) {
- node = g.node(v)
- if (ascending) {
- while ((pathV = path[pathIdx]) !== lca &&
- g.node(pathV).maxRank < node.rank) {
- pathIdx++
- }
- if (pathV === lca) {
- ascending = false
- }
- }
- if (!ascending) {
- while (pathIdx < path.length - 1 &&
- g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
- pathIdx++
- }
- pathV = path[pathIdx]
- }
- g.setParent(v, pathV)
- v = g.successors(v)[0]
- }
- })
- }
- // Find a path from v to w through the lowest common ancestor (LCA). Return the
- // full path and the LCA.
- function findPath (g, postorderNums, v, w) {
- 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 = g.parent(parent)
- vPath.push(parent)
- } while (parent &&
- (postorderNums[parent].low > low || lim > postorderNums[parent].lim))
- lca = parent
- // Traverse from w to LCA
- parent = w
- while ((parent = g.parent(parent)) !== lca) {
- wPath.push(parent)
- }
- return { path: vPath.concat(wPath.reverse()), lca: lca }
- }
- function postorder (g) {
- const result = {}
- let lim = 0
- function dfs (v) {
- const low = lim
- _.forEach(g.children(v), dfs)
- result[v] = { low: low, lim: lim++ }
- }
- _.forEach(g.children(), dfs)
- return result
- }
- export default parentDummyChains
|