题目描述#
给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入格式#
第一行包含三个正整数
接下来
接下来
输出格式#
输出包含
样例 #1#
样例输入 #1#
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5plaintext样例输出 #1#
4
4
1
4
4plaintext提示#
对于
对于
对于
样例说明:
该树结构如下:

第一次询问:
第二次询问:
第三次询问:
第四次询问:
第五次询问:
故输出依次为
{% endraw %}
{% endraw %}
{% raw %}算法分析#
本题通过倍增的方法实现
首先我们要记录各个点的深度和他们
void dfs(int now, int fath) {
fa[now][0] = fath; depth[now] = depth[fath] + 1;
for(int i = 1; i <= lg[depth[now]]; ++i)
fa[now][i] = fa[fa[now][i-1]][i-1];
for(int i = 0;i<=po[now].size()-1;i++){
if(po[now][i]!=fath) dfs(po[now][i],now);
}
}cpp加一个常数优化
for(int i = 1;i<=n;i++)lg[i] = lg[i-1] + (1 << lg[i-1] == i);//解释: gl[深度]指向2的i次方,gl[]中存的是i。cpp倍增LCA,先把两个点提到同一高度,再统一开始跳。
if(depth[x]<depth[y])swap(x,y);
for(;depth[x]>depth[y];){
x = fa[x][lg[depth[x]-depth[y]] - 1];
}//提到同一高度cpp但我们在跳的时候不能直接跳到它们的LCA,因为这可能会误判,所以我们要跳到它们LCA的下面一层,然后输出它们的父节点,这样就不会误判了。
if(x==y)return x;
for(int k = lg[depth[x]] - 1; k >= 0; --k)
if(fa[x][k] != fa[y][k])
x = fa[x][k], y = fa[y][k];
return fa[x][0];cpp{% raw %}
{% endraw %}
{% endraw %}
#include<iostream>
#include<vector>
using namespace std;
vector <int> po[500005];
int depth[500001], fa[500001][22], lg[500001];
inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c^48);
return x*f;
}
void dfs(int now, int fath) {
fa[now][0] = fath; depth[now] = depth[fath] + 1;
for(int i = 1; i <= lg[depth[now]]; ++i)
fa[now][i] = fa[fa[now][i-1]][i-1];
for(int i = 0;i<=po[now].size()-1;i++){
if(po[now][i]!=fath) dfs(po[now][i],now);
}
}
int LCA(int x,int y){
if(depth[x]<depth[y])swap(x,y);
for(;depth[x]>depth[y];){
x = fa[x][lg[depth[x]-depth[y]] - 1];
}
if(x==y)return x;
for(int k = lg[depth[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(){
int n=read(),m=read(),s=read(),g1,g2;
for(int i = 1;i<n;i++){
g1=read(),g2=read();
po[g1].push_back(g2);
po[g2].push_back(g1);
}
for(int i = 1;i<=n;i++)lg[i] = lg[i-1] + (1 << lg[i-1] == i);
dfs(s,0);
for(int i = 1;i<=m;i++){
g1=read(),g2=read();
cout<<LCA(g1,g2)<<endl;
}
}cpp{% raw %}
Comments
View on GitHub