输入 #1复制
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出 #1复制
4
4
1
4
4
倍增求lca 做法和rmq类似
#include<bits/stdc++.h>
const int maxn = 5e5 + 10;
int n, m, s;
int tot;
int head[maxn];
int depth[maxn];
int father[maxn][20];
int lg[maxn];
using namespace std;
struct node{
int to;
int next;
node() {}
node(int a, int b) : to(a), next(b) {}
}edge[maxn * 2];
void edgeadd(int a, int b){
edge[tot] = node(b, head[a]);
head[a] = tot++;
edge[tot] = node(a, head[b]);
head[b] = tot++;
}
void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
void dfs(int nw, int fa){
depth[nw] = depth[fa] + 1;
father[nw][0] = fa;
for(int i = 1; i <= lg[depth[nw]] + 1; i++)
father[nw][i] = father[father[nw][i - 1]][i - 1];
for(int i = head[nw]; i != -1; i = edge[i].next){
int v = edge[i].to;
if(v != fa)
dfs(v, nw);
}
}
int LCA(int u, int v){
if(depth[u] < depth[v])
swap(u, v);
while(depth[u] != depth[v]){
int dc = depth[u] - depth[v];
u = father[u][lg[dc]];
}
if(u == v)
return u;
for(int i = lg[depth[u]]; i >= 0; i--){
if(father[u][i] != father[v][i]){
u = father[u][i];
v = father[v][i];
}
}
return father[v][0];
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m >> s;
init();
lg[0] = -1;
for(int i = 1; i < maxn; i++)
lg[i] = lg[i >> 1] + 1;
for(int i = 1; i <= n - 1; i++){
int a, b;
cin >> a >> b;
edgeadd(a, b);
}
dfs(s, 0);
for(int i = 1; i <= m; i++){
int a, b;
cin >> a >> b;
cout << LCA(a, b) << endl;
}
}