倍增法求最近公共祖先
阿新 • • 發佈:2020-08-05
倍增法求最近公共祖先
// Created by CAD #include <bits/stdc++.h> using namespace std; const int maxn=5e5+5; vector<int> g[maxn]; int f[maxn][30],dep[maxn]; int lg[maxn]; void dfs(int x,int fa){ //預處理出深度,父親節點 f[x][0]=fa,dep[x]=dep[fa]+1; for(int i=1;i<=lg[dep[x]];++i) f[x][i]=f[f[x][i-1]][i-1]; for(auto i:g[x]) if(i!=fa) dfs(i,x); } int lca(int x,int y){ //倍增法求最近公共祖先 if(dep[x]<dep[y]) swap(x,y); while(dep[x]>dep[y]) x=f[x][lg[dep[x]-dep[y]]-1]; if(x==y) return x; for(int k=lg[dep[x]]-1;k>=0;--k) if(f[x][k]!=f[y][k]) x=f[x][k],y=f[y][k]; return f[x][0]; } int main() { int n,q,r; scanf("%d%d%d",&n,&q,&r); for(int i=1;i<=n-1;++i){ int a,b;scanf("%d%d",&a,&b); g[a].push_back(b); g[b].push_back(a); } for(int i=1;i<=n;++i) //預處理出log_2(i)+1的值 lg[i]=lg[i-1]+(1<<lg[i-1]==i); dfs(r,0); while(q--){ int x,y;scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }