-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathlca.cpp
executable file
·66 lines (65 loc) · 1.64 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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Lowest Common Ancestor by binary lifting
// https://youtu.be/8uowVvQ_-Mo?t=4306
template<typename T=int> // T: type of cost
struct lca {
int n, root, l;
vector<vector<int>> to;
vector<vector<T>> co;
vector<int> dep;
vector<T> costs;
vector<vector<int>> par;
lca(int n):n(n),to(n),co(n),dep(n),costs(n) {
l = 0;
while ((1<<l) < n) ++l;
par = vector<vector<int>>(n+1,vector<int>(l,n));
}
void addEdge(int a, int b, T c=0) {
to[a].push_back(b); co[a].push_back(c);
to[b].push_back(a); co[b].push_back(c);
}
void dfs(int v, int d=0, T c=0, int p=-1) {
if (p != -1) par[v][0] = p;
dep[v] = d;
costs[v] = c;
for (int i = 0; i < to[v].size(); ++i) {
int u = to[v][i];
if (u == p) continue;
dfs(u, d+1, c+co[v][i], v);
}
}
void init(int _root=0) {
root = _root;
dfs(root);
for (int i = 0; i < l-1; ++i) {
for (int v = 0; v < n; ++v) {
par[v][i+1] = par[par[v][i]][i];
}
}
}
// LCA
int up(int v, int k) {
for (int i = l-1; i >= 0; --i) {
int len = 1<<i;
if (k >= len) k -= len, v = par[v][i];
}
return v;
}
int operator()(int a, int b) {
if (dep[a] > dep[b]) swap(a,b);
b = up(b, dep[b]-dep[a]);
if (a == b) return a;
for (int i = l-1; i >= 0; --i) {
int na = par[a][i], nb = par[b][i];
if (na != nb) a = na, b = nb;
}
return par[a][0];
}
int length(int a, int b) {
int c = (*this)(a,b);
return dep[a]+dep[b]-dep[c]*2;
}
T dist(int a, int b) {
int c = (*this)(a,b);
return costs[a]+costs[b]-costs[c]*2;
}
};