88 lines
1.3 KiB
C++
88 lines
1.3 KiB
C++
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
|
||
const int N = 500001;
|
||
|
||
int n,m,s;
|
||
int depth[N], Log[N];
|
||
int dbl[N][20]; //倍增数组
|
||
int tot;
|
||
vector<int> graph[N];
|
||
|
||
void dfs(int cur, int fa) {
|
||
//todo
|
||
depth[cur]=depth[fa]+1;
|
||
dbl[cur][0]=fa;
|
||
for(int i=1;(1<<i)<depth[cur];i++)
|
||
{
|
||
int mid=dbl[cur][i-1];
|
||
dbl[cur][i]=dbl[mid][i-1];
|
||
}
|
||
for(int v:graph[cur])
|
||
{
|
||
if(v!=fa)
|
||
{
|
||
dfs(v,cur);
|
||
}
|
||
}
|
||
}
|
||
|
||
int lca(int x,int y) {
|
||
// 把两个点升至同一高度,再一起跳
|
||
// TODO
|
||
if(depth[x]<depth[y])
|
||
{
|
||
swap(x,y);
|
||
}
|
||
while(depth[x]>depth[y])
|
||
{
|
||
int h=Log[depth[x]-depth[y]];
|
||
x=dbl[x][h];
|
||
}
|
||
|
||
if(x==y)
|
||
return x;
|
||
|
||
// 两个点同时往上跳,跳到LCA的下一层为止
|
||
// TODO
|
||
int h=Log[depth[x]];
|
||
for(int i=h;i>=0;i--)
|
||
{
|
||
if(dbl[x][i]!=dbl[y][i])
|
||
{
|
||
x=dbl[x][i];
|
||
y=dbl[y][i];
|
||
}
|
||
}
|
||
return dbl[x][0];
|
||
}
|
||
|
||
/*
|
||
倍增算法时间复杂度是O(nlogn)
|
||
*/
|
||
int main() {
|
||
scanf("%d%d%d",&n,&m,&s);
|
||
for(int i=1; i<=n-1; i++) {
|
||
int x,y;
|
||
scanf("%d%d",&x,&y);
|
||
//todo
|
||
graph[x].push_back(y);
|
||
graph[y].push_back(x);
|
||
}
|
||
dfs(s,0); // 建树
|
||
|
||
// 预处理,常数优化
|
||
for(int i=2; i<=n; i++) {
|
||
//todo
|
||
Log[i]=Log[i/2]+1;
|
||
}
|
||
|
||
for(int i=1; i<=m; i++) {
|
||
int x,y;
|
||
scanf("%d%d",&x,&y);
|
||
printf("%d\n",lca(x,y));
|
||
}
|
||
return 0;
|
||
}
|
||
|