倍增跳一跳求树上两点间的最近公共祖先
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 }