倍增法找LCA(最短公共祖先)
题面来自牛客:https://ac.nowcoder.com/acm/problem/23482”
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
int n,m,s,a,b;
vector<int> e[N];
int dep[N],fa[N][21];
int ans,ans1,ans2,ans3;
void dfs(int u,int father){
dep[u]=dep[father]+1;
fa[u][0]=father;
for(int i=1;i<=20;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(auto v : e[u]){
if(v!=father)dfs(v,u);
}
}//处理 ST表,深度信息
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);//先让更深的点跳跃至与另一个点同深度
for(int i=log2(dep[u]-dep[v]);i>=0;i--)
if(dep[fa[u][i]]>=dep[v])
u=fa[u][i];
//现在深度相同了
if(u==v)return v;//此时两点可能在同一点,那么此点即为公共祖先
for(int i=log2(dep[u]);i>=0;i--){
if(fa[u][i]!=fa[v][i])
{u=fa[u][i],v=fa[v][i];}//两点同时上跳
}
return fa[u][0];
}
int getdis(int x,int y){
return dep[x]+dep[y]-2*dep[lca(x,y)];//通过lca获取两点的树上最短距离
}
int main(){
int n;
cin>>n;
for(int i=0;i<n-1;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);//搜索处理ST表
int u,v;
cin>>u>>v;
int q;
cin>>q;
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
ans1=(getdis(x,y));
ans2=(getdis(x,u)+getdis(v,y));
ans3=(getdis(x,v)+getdis(u,y));
cout<<min(ans1,min(ans2,ans3))<<endl;
}
}
浙公网安备 33010602011771号