cp_library_rs/graph/
lca_doubling.rs1use crate::utils::consts::Infinity;
4
5type Graph = Vec<Vec<usize>>;
6
7pub struct LCA {
10 root: usize,
11 logn: usize,
12 double: Vec<Vec<usize>>,
13 depth: Vec<usize>,
14}
15
16impl LCA {
17 pub fn new(tree: &Graph, root: usize) -> Self {
19 let n = tree.len(); let logn = n.next_power_of_two().trailing_zeros() as usize;
21 let mut double = vec![vec![0; n]; logn]; let mut depth = vec![usize::infinity(); n]; depth[0] = 0;
24 Self::dfs(root, &mut double[0], &mut depth, tree);
25
26 for i in 1..logn {
28 for j in 0..n {
29 double[i][j] = double[i - 1][double[i - 1][j]];
30 }
31 }
32
33 Self {
34 root,
35 logn,
36 double,
37 depth,
38 }
39 }
40
41 fn dfs(u: usize, par: &mut Vec<usize>, depth: &mut Vec<usize>, tree: &Graph) {
42 for &v in &tree[u] {
43 if depth[v] != usize::infinity() {
44 continue;
45 }
46 depth[v] = depth[u] + 1;
47 par[v] = u;
48 Self::dfs(v, par, depth, tree);
49 }
50 }
51
52 pub fn depth(&self, v: usize) -> usize {
54 self.depth[v]
55 }
56
57 pub fn parent(&self, v: usize) -> Option<usize> {
59 (v != self.root).then_some(self.double[0][v])
60 }
61
62 pub fn lca(&self, mut u: usize, mut v: usize) -> usize {
64 if self.depth[u] < self.depth[v] {
66 (u, v) = (v, u);
67 }
68
69 for k in 0..self.logn {
71 if ((self.depth[u] - self.depth[v]) >> k) & 1 == 1 {
72 u = self.double[k][u];
73 }
74 }
75
76 if u == v {
77 return u;
78 }
79
80 for k in (0..self.logn).rev() {
82 if self.double[k][u] != self.double[k][v] {
83 u = self.double[k][u];
84 v = self.double[k][v];
85 }
86 }
87
88 self.double[0][u]
89 }
90
91 pub fn dist(&self, u: usize, v: usize) -> usize {
93 let o = self.lca(u, v);
94 (self.depth[u] - self.depth[o]) + (self.depth[v] - self.depth[o])
95 }
96
97 pub fn kth_ancestor(&self, mut v: usize, k: usize) -> Option<usize> {
99 if k > self.depth(v) {
100 return None;
101 }
102 for i in 0..self.logn {
103 if (k >> i) & 1 == 1 {
104 v = self.double[i][v];
105 }
106 }
107 Some(v)
108 }
109
110 pub fn kth_on_path(&self, u: usize, v: usize, k: usize) -> Option<usize> {
112 let o = self.lca(u, v);
113 let dist_u_o = self.depth[u] - self.depth[o];
114 if k <= dist_u_o {
115 self.kth_ancestor(u, k)
116 } else {
117 let dist_v_o = self.depth[v] - self.depth[o];
118 (dist_v_o + dist_u_o)
119 .checked_sub(k)
120 .and_then(|l| self.kth_ancestor(v, l))
121 }
122 }
123}