首页 > 其他 > 详细

倍增求LCA模板

时间:2020-05-02 11:33:23      阅读:39      评论:0      收藏:0      [点我收藏+]
//dfs预处理出每个节点的深度和2的x方级祖先节点
void dfs(int now,int fa,int da){
//now为当前节点,fa为父亲节点,da为父亲节点和儿子节点所连边的边权
    cost[now][0]=da;
    zx[now][0]=fa;
    dep[now]=dep[fa]+1;
//cost[x][i]表示x节点到它的2的i次方级祖先节点的距离
//zx[x][i]表示x节点的2的i次方级祖先节点的编号
//dep[x]表示x节点的深度
    for(int i=1;(1<<i)<=dep[now];i++){
        zx[now][i]=zx[zx[now][i-1]][i-1];
//类似于你父亲的父亲是你的祖父
        cost[now][i]=cost[now][i-1]+cost[zx[now][i-1]][i-1];
    }
//处理出now的2的i次方级节点的编号和now到now的2的i次方级祖先节点的距离
    for(int i=head[now];i!=-1;i=b[i].next){
        if(fa!=b[i].to) dfs(b[i].to,now,b[i].val);
//递归处理
    }
}
int lca(int x,int y){
//查询x与y的LCA
    int ans=0;
    if(dep[x]>dep[y]) swap(x,y);
//使x的深度小于y的深度
    int len=dep[y]-dep[x],k=0;
    while(len){
    	if(len & 1){
            ans+=cost[y][k];
            y=zx[y][k];
        }
    	++k;len>>=1;
    }
//将y调到与x相同的深度,同时累加距离
    if(x==y) return ans;
//如果调到相同深度后两节点重合,直接返回权值就可以
    for(int i=20;i>=0;i--){
        if(zx[x][i]==zx[y][i]) continue;
        ans+=cost[x][i]+cost[y][i];
        x=zx[x][i];
        y=zx[y][i];
    }
//将x和y向上跳,直到它们的父亲节点相同
    return ans+cost[x][0]+cost[y][0];
//返回累加的权值与x,y到它们的父亲节点的权值
}

倍增求LCA模板

原文:https://www.cnblogs.com/liuchanglc/p/12816848.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!