倍增求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
提示
对于 的数据,,。
对于 的数据,,。
对于 的数据,,。
样例说明:
该树结构如下:
第一次询问: 的最近公共祖先,故为 。
第二次询问: 的最近公共祖先,故为 。
第三次询问: 的最近公共祖先,故为 。
第四次询问: 的最近公共祖先,故为 。
第五次询问: 的最近公共祖先,故为 。
故输出依次为 。
2021/10/4 数据更新 @fstqwq:应要求加了两组数据卡掉了暴力跳。
代码
// 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) //fw #include<bits/stdc++.h> #define pii pair <int, int> #define pll pair <ll, ll> #define endl '\n' #define il inline #define pb push_back #define fi first #define se second #define lc u<<1 #define rc u<<1|1 using namespace std; typedef long long ll; const int N=5e5+5,M=2*N;//开双向边 int h[N],e[M],ne[M],idx;//前向星 int fa[N][25],q[N];//fa[i][j]从i开始跳2^j步跳到的点 int n,m,root; int depth[N];//每个点的深度,用于把a,b跳到同一层 void add(int a,int b)//前向星加边 { e[idx]=b; ne[idx]=h[a]; h[a]=idx++; } void bfs() { memset(depth,0x3f,sizeof depth);//深度初始化 depth[0]=0;depth[root]=1;//定义0号点为哨兵,防止跳过头 q[0]=root; int hh=0,tt=0; while(hh<=tt)//宽搜计算深度 { int t=q[hh++]; for(int i=h[t];~i;i=ne[i]) { int j=e[i]; if(depth[j]>depth[t]+1) { depth[j]=depth[t]+1; q[++tt]=j; fa[j][0]=t;//倍增求fa,与st表类似 for(int k=1;k<=20;k++) { fa[j][k]=fa[fa[j][k-1]][k-1]; } } } } } int lca(int a,int b) { if(depth[a]<depth[b])swap(a,b);//用a表示较深的点 for(int k=20;k>=0;k--)//把a和b跳到同一层 { if(depth[fa[a][k]]>=depth[b]) a=fa[a][k]; } if(a==b)return a;//如果跳到同一层后相等,则说明这个点就是最近公共祖先 for(int k=20;k>=0;k--)//如果不相等则,两个点一起往上跳 { if(fa[a][k]!=fa[b][k])//如果跳过头或者两个点的父节点是一个点则不跳 { a=fa[a][k]; b=fa[b][k]; } } return fa[a][0];//返回父节点即lca } int main() { memset(h,-1,sizeof h);//前向星初始化 cin>>n>>m>>root; for(int i=1;i<=n-1;i++) { int a,b; cin>>a>>b; add(a,b),add(b,a); } bfs();//预处理出depth和fa while(m--)//处理每组询问 { int a,b; cin>>a>>b; cout<<lca(a,b)<<endl; } return 0; }
一个菜鸡
本文作者:Avarice_Zhao
本文链接:https://www.cnblogs.com/avarice/p/16418818.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步