导航

倍增法lca

Posted on 2016-03-22 08:51  tun~  阅读(232)  评论(0编辑  收藏  举报
int dep[N],rt[25][N],siz[N];//rt数组需要在dfs之前置-1。

void dfs(int pos,int deep){
    dep[pos]=deep;
    siz[pos]=1;
    for(edge *it=adj[pos];it;it=it->next){
        if(!dep[it->id]){
            rt[0][it->id]=pos;
            dfs(it->id,deep+1);
            siz[pos]+=siz[it->id];
        }
    }
}

void prelca(){
    for(int i=1;i<=20;i++){
        for(int j=1;j<=n;j++){
            rt[i][j]=rt[i-1][j]==-1?-1:rt[i-1][rt[i-1][j]];
        }
    }
}

int LCA(int u,int v){//查询u和v的lca
    if(dep[u]<dep[v])swap(u,v);
    for(int i=0;i<21;i++){
        if((dep[u]-dep[v])>>i&1){
            u=rt[i][u];
        }
    }
    if(u==v)return u;
    for(int i=19;i>=0;i--){
        if(rt[i][u]!=rt[i][v]){
            u=rt[i][u];
            v=rt[i][v];
        }
    }
    return rt[0][u];
}

int jump(int pos,int num){//查询节点pos的第num个父亲
    for(int i=0;i<21;i++){
        if(num>>i&1){
            pos=rt[i][pos];
        }
    }
    return pos;
}