MCPcopy Create free account
hub / github.com/TheAlgorithms/JavaScript / BinaryLifting

Class BinaryLifting

Graphs/BinaryLifting.js:12–70  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

10 */
11
12export class BinaryLifting {
13 constructor(root, tree) {
14 this.root = root
15 this.connections = new Map()
16 this.up = new Map() // up[node][i] stores the 2^i-th parent of node
17 for (const [i, j] of tree) {
18 this.addEdge(i, j)
19 }
20 this.log = Math.ceil(Math.log2(this.connections.size))
21 this.dfs(root, root)
22 }
23
24 addNode(node) {
25 // Function to add a node to the tree (connection represented by set)
26 this.connections.set(node, new Set())
27 }
28
29 addEdge(node1, node2) {
30 // Function to add an edge (adds the node too if they are not present in the tree)
31 if (!this.connections.has(node1)) {
32 this.addNode(node1)
33 }
34 if (!this.connections.has(node2)) {
35 this.addNode(node2)
36 }
37 this.connections.get(node1).add(node2)
38 this.connections.get(node2).add(node1)
39 }
40
41 dfs(node, parent) {
42 // The dfs function calculates 2^i-th ancestor of all nodes for i ranging from 0 to this.log
43 // We make use of the fact the two consecutive jumps of length 2^(i-1) make the total jump length 2^i
44 this.up.set(node, new Map())
45 this.up.get(node).set(0, parent)
46 for (let i = 1; i < this.log; i++) {
47 this.up
48 .get(node)
49 .set(i, this.up.get(this.up.get(node).get(i - 1)).get(i - 1))
50 }
51 for (const child of this.connections.get(node)) {
52 if (child !== parent) this.dfs(child, node)
53 }
54 }
55
56 kthAncestor(node, k) {
57 // if value of k is more than or equal to the number of total nodes, we return the root of the graph
58 if (k >= this.connections.size) {
59 return this.root
60 }
61 // if i-th bit is set in the binary representation of k, we jump from a node to its 2^i-th ancestor
62 // so after checking all bits of k, we will have made jumps of total length k, in just log k steps
63 for (let i = 0; i < this.log; i++) {
64 if (k & (1 << i)) {
65 node = this.up.get(node).get(i)
66 }
67 }
68 return node
69 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected