[模板]最近公共祖先LCA
Posted nlyzl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板]最近公共祖先LCA相关的知识,希望对你有一定的参考价值。
本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:传送门
倍增求LCA模板
code:
#include<bits/stdc++.h> #pragma GCC optimize(3) using namespace std; int n,q,a,b,tot,m; int nxt[1000010],head[1000010],ver[1000010],dep[1000010],f[1000010][21]; //设f[x,k]表示x的2^k辈祖先,即从x向根节点走2^k步到达的节点 inline int read() int x=0,f=1;char ch=getchar(); while(!isdigit(ch))if(ch==‘-‘)f=-1;ch=getchar(); while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48);ch=getchar(); return x*f; void put(int x,int y) ++tot; ver[tot]=y; nxt[tot]=head[x]; head[x]=tot; void dfs(int x,int fa)//预处理 深度及到达根节点的步数 dep[x]=dep[fa]+1;//初始化深度 for(int i=0;i<=19;i++)//或者 i=1;i<=20;i++ f[x][i+1]=f[f[x][i]][i];//f[x][i]=f[f[x][i-1]][i-1] //注意:当i=1 to 20 时 f数组要都要开21,否则会爆零 for(int i=head[x];i;i=nxt[i]) int y=ver[i]; if(y==fa)continue; f[y][0]=x; //y向上跳2^0=1就是x,因为y是x的子节点 dfs(y,x); int lca(int x,int y) if(dep[x]<dep[y])//使x深度大于y swap(x,y); for(int i=20;i>=0;i--)//一定要写逆循环 if(dep[f[x][i]]>=dep[y])//把x向上调整到与y同一深度 x=f[x][i]; if(x==y)//如果在同一分支上,直接输出,因为此时x,y的LCA即本身 return x; for(int i=20;i>=0;i--) //此时x,y已跳到同一层 if(f[x][i]!=f[y][i]) //如果f[x][i]和f[y][i]不同才跳,因为相同就表示已经找到根节点 x=f[x][i];//不断更新 y=f[y][i];//不断更新 return f[x][0];//当无法在跳时,根节点(父亲节点) 距离字节点只有一步 int main() n=read(),q=read(),m=read(); for(int i=1;i<n;i++) a=read(),b=read(); put(a,b); put(b,a); dfs(m,0);//以m为根开始遍历 for(int i=1;i<=q;i++) a=read(),b=read(); printf("%d\n",lca(a,b)); return 0;
以上是关于[模板]最近公共祖先LCA的主要内容,如果未能解决你的问题,请参考以下文章