倍增lca

// Problem: P3379 【模板】最近公共祖先(LCA)
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3379
// Memory Limit: 512 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int mn=500005;
int n,m,s;
int d[mn],f[mn][21];//depth,f[i][j]表示i向上跳pow(2,j)次到达的点
vector<int> v[mn];
void dfs(int x,int y)
{
f[x][0]=y;//跳一次就是父亲
d[x]=d[y]+1;
for(int i=1;i<=20;i++)
{
f[x][i]=f[f[x][i-1]][i-1];//跳pow(2,j-1)次到的点跳pow(2,j-1)次就是跳了pow(2,j)次
}
for(int i=0;i<v[x].size();i++)
{
if(v[x][i]!=y)
{
dfs(v[x][i],x);
}
}
}
int lca(int x,int y)
{
if(d[x]<d[y])
{
swap(x,y);
}
int a=d[x]-d[y];
for(int i=0;i<=20;i++)
{
if((a>>i)&1)x=f[x][i];//让两点在同一深度
}
if(x==y)return x;
for(int i=20;i>=0;i--)
{
if(f[x][i]!=f[y][i])//不相等说明可以跳
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
int main()
{
cin>>n>>m>>s;
int x,y;
for(int i=1;i<n;i++)
{
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dfs(s,0);
while(m--)
{
cin>>x>>y;
cout<<lca(x,y)<<'\n';
}
return 0;
}

本文作者:stawalr

本文链接:https://www.cnblogs.com/ikusiad/p/18705295

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   ikusiad  阅读(9)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起