P3379 【模板】最近公共祖先(LCA) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
const int N=5e5+100;
const int inf=0x3f3f3f;
int n,m,s;
vector<int>g[N];
int dep[N];//存u点的深度
int fa[N][20];//存从u点向上跳2^i层的祖先节点
void dfs(int u,int father)
{dep[u]=dep[father]+1;//该点深度为他的父节点深度加1fa[u][0]=father;//当前节点向上跳一步就是他的父节点for(int i=1;i<=19;i++)fa[u][i]=fa[fa[u][i-1]][i-1];//递推点的所有能跳到的祖先节点,越界为0for(auto i:g[u])if(i!=father)dfs(i,u);
}
int lca(int u,int v)
{if(dep[u]<dep[v])//让u点跳swap(u,v);/*for(int i=19;i>=0;i--)//先让两点到达同一层{if(dep[fa[u][i]]>=dep[v])//u节点跳到祖先节点后的深度大于v点的深度u=fa[u][i];//u点变到其祖先节点处}*/int dx=dep[u]-dep[v];for(int i=0;dx>0;i++,dx=dx/2){if(dx&1){u=fa[u][i];}}//两种写法,让两点到达同一层if(u==v)//特判,v点为u的祖先节点return v;for(int i=19;i>=0;i--){if(fa[u][i]!=fa[v][i])//两点跳后的祖先节点的父节点是否相等,不相等i-1u=fa[u][i],v=fa[v][i];//停在最近公共祖先的下层的儿子节点(此时两点的父节点就是公共最近祖先)}return fa[u][0];//再跳最后一步到达公共祖先位置
}
int main()
{scanf("%d%d%d",&n,&m,&s);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);g[x].push_back(y);g[y].push_back(x);}dfs(s,0);//从根节点遍历树while(m--){int a,b;scanf("%d%d",&a,&b);printf("%d\n",lca(a,b));}return 0;
}