最近树上公共祖先(LCA)
零 前置芝士
st表
一 正题
先预处理出来 数组,其中 代表 的 级祖先。
对于每一组询问 ,找到深度大的那个点,让他先跳到和另一个一样的高度,然后一起往上跳,最后输出父亲节点。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,m,s;
int head[N],nxt[N<<1],to[N<<1],cnt;
inline void add(int u,int v){
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
int dep[N],fa[N][22],lg[N];
void dfs(int u,int f){
fa[u][0]=f;
dep[u]=dep[f]+1;
for(int i=1;i<=lg[dep[u]];i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=nxt[i])
if(to[i]!=f) dfs(to[i],u);
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y])
x=fa[x][lg[dep[x]-dep[y]]-1];
if(x==y) return x;
for(int k=lg[dep[x]]-1;k>=0;k--)
if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
return fa[x][0];
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
add(x,y); add(y,x);
}
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
for(int i=1;i<=n;i++)
printf("%d %d\n",i,lg[i]);
dfs(s,0);
for(int i=1,x,y;i<=m;i++){
cin>>x>>y;
printf("%d\n",lca(x,y));
}
return 0;
}
二 例题
略,随便找都能找到
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】