ProgramAlgTrain/20240919/CSP常考算法模板/P3379【模板】LCA_倍增 -邻接表.cpp
2024-09-19 11:11:59 +08:00

88 lines
1.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}