最近公共祖先(LCA)(倍增)
【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入格式
第一行包含三个正整数
接下来
接下来
输出格式
输出包含
样例 #1
样例输入 #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
提示
对于
对于
对于
样例说明:
该树结构如下:
第一次询问:
第二次询问:
第三次询问:
第四次询问:
第五次询问:
故输出依次为
解题思路
1.暴力思路
很容易想到一个暴力思路:
假设要求
暴力代码:
void dfs(int i,int d,int father){
de[i]=d;//求出de数组
fa[i]=father;//求出fa数组
for(int j=head[i];j;j=next[j]){
if(ver[j]!=father)dfs(ver[j],d+1,i);//dfs
}
}
int getlca(int x,int y){
if(x==y)return x;
while(x!=y){
if(de[x]==de[y])x=fa[x],y=fa[y];//一起向上跳
else if(de[x]>de[y])x=fa[x];//如果深度不一样就跳
else if(de[x]<de[y])y=fa[y];
}
return x;
}
2.倍增祖先
暴力思路会有个问题,比如树退化成一条链,就会
我们能不能想办法加快跳的速度呢? 我们可以使用倍增的方式加快跳。如:
每次跳到最远能跳的点,这样能大大减少跳的次数。所以我们在
转移方程为:
倍增代码:
void dfs(int i,int d,int father){
de[i]=d,f[i][0]=father;//求出de数组
for(int j=1;j<=log2(d);j++)f[i][j]=f[f[i][j-1]][j-1];//求出f数组
for(int j=head[i];j;j=next[j]){
if(ver[j]!=father)dfs(ver[j],d+1,i);//dfs
}
}
int getlca(int x,int y){
if(de[x]<de[y])swap(x,y);
for(int i=19;i>=0;i--){//如果深度不一样就跳
if(de[f[x][i]]>=de[y])x=f[x][i];
if(x==y)return x;
}
for(int i=19;i>=0;i--){//一起向上跳
if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
}
return f[x][0];
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/16426588.html,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效