|
1 | 1 | """
|
2 | 2 | Binary lifting technique applied to a tree.
|
3 |
| -There are three different uses of this implementation |
| 3 | +There are four different uses of this implementation |
4 | 4 |
|
5 | 5 | 1. Computing LCA in O(log n) time.
|
6 | 6 |
|
|
15 | 15 | BL = binary_lift(graph, root=0)
|
16 | 16 | print(BL.lca(2, 3)) # prints 1
|
17 | 17 |
|
18 |
| -2. Compute the distance between two nodes in O(log n) time. |
| 18 | +2. Compute the k-th ancestor of a node in O(log k) time. |
| 19 | +
|
| 20 | + Example: |
| 21 | + graph = [[1], [0, 2, 3], [1], [1]] |
| 22 | + BL = binary_lift(graph, root=0) |
| 23 | + print(BL.kth_ancestor(2, 2)) # prints 0 |
| 24 | + print(BL.kth_ancestor(2, 3)) # prints -1 |
| 25 | +
|
| 26 | +3. Compute the distance between two nodes in O(log n) time. |
19 | 27 |
|
20 | 28 | Example:
|
21 | 29 | graph = [[1], [0, 2, 3], [1], [1]]
|
22 | 30 | BL = binary_lift(graph)
|
23 | 31 | print(BL.distance(2, 3)) # prints 2
|
24 | 32 |
|
25 |
| -3. Compute the sum/min/max/... of the weight |
| 33 | +4. Compute the sum/min/max/... of the weight |
26 | 34 | of a path between a pair of nodes in O(log n) time.
|
27 | 35 |
|
28 | 36 | res = Path[0]
|
@@ -87,7 +95,17 @@ def lca(self, a, b):
|
87 | 95 | return a
|
88 | 96 |
|
89 | 97 | def distance(self, a, b):
|
90 |
| - return self.depth[a] + self.depth[b] - 2 * self.depth[self.lca(a,b)] |
| 98 | + return self.depth[a] + self.depth[b] - 2 * self.depth[self.lca(a,b)] |
| 99 | + |
| 100 | + def kth_ancestor(self, a, k): |
| 101 | + parent = self.parent |
| 102 | + d = self.depth[a] |
| 103 | + if d < k: |
| 104 | + return -1 |
| 105 | + for i in range(d.bit_length()): |
| 106 | + if (d >> i) & 1: |
| 107 | + a = parent[i][a] |
| 108 | + return a |
91 | 109 |
|
92 | 110 | def __call__(self, a, b):
|
93 | 111 | depth = self.depth
|
|
0 commit comments