-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLCA.cpp
85 lines (69 loc) · 1.85 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const int max_nodes, log_max_nodes;
int num_nodes, log_num_nodes, root;
vector<int> children[max_nodes]; // children[i] contains the children of node i
int A[max_nodes][log_max_nodes+1]; // A[i][j] is the 2^j-th ancestor of node i, or -1 if that ancestor does not exist
int L[max_nodes]; // L[i] is the distance between node i and the root
// floor of the binary logarithm of n
int lb(unsigned int n)
{
if(n==0)
return -1;
int p = 0;
if (n >= 1<<16) { n >>= 16; p += 16; }
if (n >= 1<< 8) { n >>= 8; p += 8; }
if (n >= 1<< 4) { n >>= 4; p += 4; }
if (n >= 1<< 2) { n >>= 2; p += 2; }
if (n >= 1<< 1) { p += 1; }
return p;
}
void DFS(int i, int l)
{
L[i] = l;
for(int j = 0; j < children[i].size(); j++)
DFS(children[i][j], l+1);
}
int LCA(int p, int q)
{
// ensure node p is at least as deep as node q
if(L[p] < L[q])
swap(p, q);
// "binary search" for the ancestor of node p situated on the same level as q
for(int i = log_num_nodes; i >= 0; i--)
if(L[p] - (1<<i) >= L[q])
p = A[p][i];
if(p == q)
return p;
// "binary search" for the LCA
for(int i = log_num_nodes; i >= 0; i--)
if(A[p][i] != -1 && A[p][i] != A[q][i])
{
p = A[p][i];
q = A[q][i];
}
return A[p][0];
}
int main(int argc,char* argv[])
{
// read num_nodes, the total number of nodes
log_num_nodes=lb(num_nodes);
for(int i = 0; i < num_nodes; i++)
{
int p;
// read p, the parent of node i or -1 if node i is the root
A[i][0] = p;
if(p != -1)
children[p].push_back(i);
else
root = i;
}
// precompute A using dynamic programming
for(int j = 1; j <= log_num_nodes; j++)
for(int i = 0; i < num_nodes; i++)
if(A[i][j-1] != -1)
A[i][j] = A[A[i][j-1]][j-1];
else
A[i][j] = -1;
// precompute L
DFS(root, 0);
return 0;
}