树上带权lca

最近有一次考试有两个测试点是裸的树上带权lca,然而我那10分都没有拿到,我真菜的可以

问题简单描述:给你一棵树,树的边都有边权,有很多询问,求两点之间的距离

首先看下面一个例子

我们以1为树根,然后我们设置一个数组dep[ ]表示从根出发每个节点的深度,例如dep[1]=1,dep[2]=2,dep[3]=2...

再设置一个数组dis[ ]表示从根节点出发到每个点的距离 ,例如dis[1]=0,dis[2]=3,dis[4]=9

假定lca(x,y)表示x和y两个节点的最近公共祖先,那么x到y的距离显然等于dis[x]+dis[y]-2*dis[lca(x,y)]

然后我们看看预处理代码

void build(int u,int fa){
    for(int i=1;i<25;i++){
        f[u][i]=f[f[u][i-1]][i-1];
    }
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(v==fa)continue;
        dis[v]=dis[u]+wei[i];
        dep[v]=dep[u]+1;
        f[v][0]=u;
        build(v,u);
    }
}

其中f[i][j] 表示从i节点出发向上走2^{j}步到达的节点显然f[u][0]=u的父节点 然后递归下去就可以求出来了

然后就是lca函数了

int lca(int x,int y){
    if(dep[x]<dep[y]){
        swap(x,y);
    }
    for(int i=24;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]){
            x=f[x][i];
        }
        if(x==y)return x;
    }
    for(int i=24;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i],y=f[y][i];
        }
    }
    return f[x][0];
}

我们假定dep[x]>=dep[y] 那么首先我们要让x和y的深度一样,然后再一起向上跳找到最近公共祖先

然后下面一个for循环就是一起跳了,注意:这里一定要从大到小for

至于理解的话,就是如果从小到大for,刚开始跳了一点点步数,后面还差一点点,然后一下又跳很多次,就跳不到了

所以要从大到小for,根据任何一个数一定能表示成二进制的形式,然后就一定能找到。

ok!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值