1
+ // Finding LCA in a tree using binary lifting
2
+ // Pre processing TC: O(nlogn)
3
+ // TC for finding LCA per query: O(logn)
4
+
5
+ #include < bits/stdc++.h>
6
+ using namespace std ;
7
+
8
+ constexpr int N = 5 ; // No. of vertices
9
+ constexpr int L = 4 ; // ceil(logN / log2) + 1
10
+
11
+ // Vertices from 1 to N.
12
+ vector<int > adj[N + 1 ];
13
+ int up[N + 1 ][L];
14
+ int level[N + 1 ];
15
+
16
+ void dfs (int u, int prev = 0 )
17
+ {
18
+ up[u][0 ] = prev;
19
+ for (auto &v : adj[u])
20
+ {
21
+ if (v == prev) continue ;
22
+
23
+ level[v] = level[u] + 1 ;
24
+ dfs (v, u);
25
+ }
26
+ }
27
+
28
+ void binaryLift ()
29
+ {
30
+ dfs (1 );
31
+ for (int i = 1 ; i < L; i++)
32
+ for (int j = 1 ; j <= N; j++)
33
+ up[j][i] = up[up[j][i - 1 ]][i - 1 ];
34
+ }
35
+
36
+ int LCA (int a, int b)
37
+ {
38
+ if (level[a] > level[b])
39
+ swap (a, b);
40
+
41
+ int diff = level[b] - level[a];
42
+ for (int i = 0 ; i < L; i++)
43
+ {
44
+ if ((diff & (1 << i)))
45
+ b = up[b][i];
46
+ }
47
+
48
+ if (a == b) return a;
49
+
50
+ for (int i = L - 1 ; i >= 0 ; i--)
51
+ {
52
+ if (up[a][i] != up[b][i])
53
+ {
54
+ a = up[a][i];
55
+ b = up[b][i];
56
+ }
57
+ }
58
+ return up[a][0 ];
59
+ }
60
+
61
+ void addEdge (int u, int v)
62
+ {
63
+ adj[u].push_back (v);
64
+ adj[v].push_back (u);
65
+ }
66
+
67
+ int dist (int a, int b)
68
+ {
69
+ return level[a] + level[b] - 2 * level[LCA (a, b)];
70
+ }
71
+
72
+ int main ()
73
+ {
74
+ addEdge (1 , 2 );
75
+ addEdge (1 , 3 );
76
+ addEdge (2 , 4 );
77
+ addEdge (2 , 5 );
78
+
79
+ binaryLift ();
80
+
81
+ cout << " LCA:\n " ;
82
+ cout << LCA (4 , 3 ) << " \n " ;
83
+ cout << LCA (4 , 5 ) << " \n " ;
84
+ cout << LCA (4 , 2 ) << " \n " ;
85
+
86
+ cout << " Distances:\n " ;
87
+ cout << dist (4 , 3 ) << " \n " ;
88
+ cout << dist (4 , 5 ) << " \n " ;
89
+ cout << dist (4 , 2 ) << " \n " ;
90
+
91
+ return 0 ;
92
+ }
0 commit comments