-
Notifications
You must be signed in to change notification settings - Fork 0
/
LCA.cpp
46 lines (45 loc) · 1.18 KB
/
LCA.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
vector<int> tree[100010];
class LCA {
public:
int n, ln; // number of nodes and its log
vector<vector<int>> parent;
vector<int> depth;
LCA(int _n, int root=-1) : n(_n), depth(_n){
ln=0;
while(n>=(1<<ln)) ln++; // calc log n
parent = vector<vector<int>>(ln, vector<int>(n));
if(root!=-1) init(root);
}
void dfs(const int v, const int p, const int d){
parent[0][v] = p;
depth[v] = d;
for(auto to : tree[v]) if(to != p) dfs(to, v, d+1);
}
void init(const int root){
dfs(root, -1, 0);
for(int k=0; k+1<ln; k++){
for(int v=0; v<n; v++){
if(parent[k][v] < 0) parent[k+1][v] = -1;
else parent[k+1][v] = parent[k][parent[k][v]];
}
}
}
int query(int u, int v) const {
if(depth[u] > depth[v]) swap(u,v);
for(int k=0; k<ln; k++){
if((depth[v]-depth[u])>>k & 1) v = parent[k][v];
}
if(u==v) return u;
for(int k=ln-1; k>=0; k--){
if(parent[k][u] != parent[k][v]){
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
int distance(int a, int b) const { // only for unweighted graph
int p = query(a,b);
return depth[a] + depth[b] - 2*depth[p];
}
};