【模板】倍增lca

倍增跳一跳求树上两点间的最近公共祖先

 1 //倍增lca
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int MAXN = 500000 + 1;
 8 const int MAXM = 500000 + 1;
 9 const int K = 20 + 1;
10 
11 int n, m, s;
12 int deep[MAXN], f[MAXN][K];
13 int edge_num, head[MAXN];
14 struct Edge {
15     int to, next;
16 }h[MAXM << 1];
17 
18 inline int read() {
19     int x = 0, f = 1; char ch = getchar();
20     while(ch < '0' || ch > '9') {
21         if(ch == '-') f = -1;
22         ch = getchar();
23     }
24     while(ch >= '0' && ch <= '9')
25         x = (x << 3) + (x << 1) + ch - 48, ch = getchar();
26     return x * f;
27 }
28 
29 inline void Add(int from, int to) {
30     h[++edge_num].to = to;
31     h[edge_num].next = head[from];
32     head[from] = edge_num;
33 }
34 
35 void build(int u) {
36     for(int i = head[u]; i != -1; i = h[i].next)
37         if(!deep[h[i].to]) {
38             deep[h[i].to]=deep[u]+1;
39             f[h[i].to][0]=u;
40             build(h[i].to);
41         }
42 }
43 
44 void fill() {
45     for(int j = 1; j < K; ++j)
46     for(int i = 1; i <= n; ++i)
47         f[i][j] = f[f[i][j - 1]][j - 1];
48 }
49 
50 int lca(int a, int b) {
51     if(deep[a] > deep[b])
52         swap(a, b);
53     for(int i = K - 1; i >= 0; --i)
54         if(deep[f[b][i]] >= deep[a]) b = f[b][i];
55     if(a == b) return a;
56     for(int i = K - 1; i >= 0; --i) {
57         if(f[a][i] != f[b][i]) {
58             a = f[a][i], b = f[b][i];
59         }
60     }
61     return f[b][0];
62 }
63 
64 int main() {
65     n = read(), m = read(), s = read();
66     memset(head, -1, sizeof(head));
67     for(int i = 1; i < n; ++i) {
68         int x = read(), y = read();
69         Add(x, y);
70         Add(y, x);
71     }
72     deep[s] = 1;
73     build(s);
74     fill();
75     while(m--) {
76         int a = read(), b = read();
77         printf("%d\n", lca(a, b));
78     }
79 }

题目传送门

猜你喜欢

转载自www.cnblogs.com/devilk-sjj/p/9048434.html