AcWing1172 祖孙询问(倍增法求lca模板)

注意点:

要倒序,否则无法刚好二进制拼凑

设置哨兵,0的深度为0,且超过树的根节点的值为=0

#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=5e5+10;
const int inf=0x3f3f3f3f;
int root;
int idx,h[N],e[N],ne[N];
int fa[N][16];
int depth[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int root){
    queue<int> q;
    memset(depth,0x3f,sizeof depth);
    depth[0]=0,depth[root]=1;
    q.push(root);
    while(q.size()){
        int t=q.front();
        q.pop();
        int i;
        for(i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            if(depth[j]>depth[t]+1){
                depth[j]=depth[t]+1;
                q.push(j);
                fa[j][0]=t;
                for(int k=1;k<=15;k++){
                    fa[j][k]=fa[fa[j][k-1]][k-1];
                }
            }
        }
    }
}
int lca(int x,int y){
    if(depth[x]<depth[y])
        swap(x,y);
    int i;
    for(i=15;i>=0;i--){
        if(depth[fa[x][i]]>=depth[y])
            x=fa[x][i];
    }
    if(x==y)
        return x;
    for(i=15;i>=0;i--){
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
int main(){
    int n,m;
    cin>>n;
    memset(h,-1,sizeof h);
    int i;
    int a,b;
    for(i=1;i<=n;i++){
        scanf("%d%d",&a,&b);
        if(b==-1){
         root=a;
        }
        else{
            add(a,b);
            add(b,a);
        }
    }
    cin>>m;
    bfs(root);
    while(m--){
        int x,y;
        cin>>x>>y;
        int p=lca(x,y);
        if(p==x)
            cout<<1<<endl;
        else if(p==y)
            cout<<2<<endl;
        else
            cout<<0<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12484397.html