树链剖分之重链剖分详解

一些概念

在学习重链剖分前,首先要明白以下几个概念:

  1. 中二重儿子:就是一个节点的儿子中最“重”的那个,“重”表示的是子树大小最大,如果都一样大,就随便选一个就好了(用 s o n son son数组存储)
  2. 轻儿子:除了重儿子外其他的儿子
  3. 重边:重儿子和父亲之间的边
  4. 轻边:轻儿子和父亲之间的边
  5. 重链:重边连在一起形成的链
  6. 轻链:轻边连在一起形成的链(貌似没啥用)
  7. 重链顶点:一条重链中,深度最小的点(用 t o p top top数组记录)

为了方便大家理解,这里我画了一张图,来表示重链剖分后的结果:
重链剖分后的结果
其中,红色的线表示重边,连在一起,形成 3 3 3条重链;黑色的线表示轻边,连在一起,形成 3 3 3条轻链
这样,大家对这些概念应该都了解了吧?

算法讲解

接下来,我们来介绍如何进行重链剖分
首先,我们进行第一遍dfs,求出子树的大小( s i z siz siz),重儿子( s o n son son),父亲节点( f a fa fa)和每个点的深度( d e p dep dep
s i z e size size f a fa fa d e p dep dep的求法就不用说了吧……
我们来讲讲 s o n son son的求法
首先,设一个变量 m a x s o n maxson maxson,初值为 − 1 -1 1,记录最大的子树大小
接着,对于枚举的每棵子树,假设当前枚举的子树的根为 v v v,判断 m a x s o n maxson maxson s i z [ v ] siz[v] siz[v]的大小
如果 s i z [ v ] > m a x s o n siz[v]>maxson siz[v]>maxson,那么 s o n [ u ] = v son[u]=v son[u]=v
代码:

int dfs1(int x,int Fa,int Dep)
{
   
    dep[x]=Dep,fa[x]=Fa,siz[x]=1;
    int maxson=-1;
    for(int i=head[x];i!=-1;i=e[i].nxt) if(e[i].v!=Fa){
   
        siz[x]+=dfs1(e[i].v,x,Dep+1);
        if(siz[e[i].v]>maxson) maxson=siz[e[i].v],son[x]=e[i].v;
    }
    return siz[x];
}

接着,我们来讲一讲第二个dfs,这个dfs要求出dfs序( d f n dfn dfn)和重链顶点( t o

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值