树链剖分,顾名思义就是将树形的结构剖分成链,我们以此便于在链上操作

首先我们需要明白在树链剖分中的一些概念

重儿子:某节点所有儿子中子树最多的儿子

重链:有重儿子构成的链

dfs序:按重儿子优先遍历时的顺序

轻儿子的意思就与重儿子相反

首先是第一个dfs操作

在本次操作中,我们主要做的是处理所有节点的父亲,子树大小,重儿子,深度等操作

void dfs1(int now,int father,int deep)
{
    tree[now].depth=deep;//初始化当前节点的深度,子树大小,父亲
    tree[now].size=;
    tree[now].fa=father;
    maxson=-;
    for(int i=head[now];i;i=tree[i].next)
    {
        int v=tree[now].to;
        if(v==tree[now].father)//因为练的是双向边,所以不免会练到自己的父亲节点,就跳过
        {
            continue;
        }
        dfs(v,now,deep+);
        tree[now].size+=tree[v].size;//累加子树的大小
        if(tree[v].size>maxson)
        {
            tree[now].son=v;
            maxson=size[v];
        }
    }
} 

接下来就是第二次dfs操作,将树剖分成链的过程

我们在这时就有一个非常重要的东西那就是dfs序

dfs序就是我们遍历时的顺序,在这里的遍历方式是二叉树的中序遍历

因为我们在树链剖分中是以重儿子优先

所以dfs序可能会与实际有出入

所以我们还需新开一个数组来维护新的dfs序

以便于我们的线段树操作

但蒟蒻太弱,以后再来讲套线段树的事情

我们先好好的剖分吧

void dfs2(int now,int topf)//从当前节点开始,topf为当前链的顶端
{
    tree[now].index=++TIME;//dfs序
    w[tree[now].index]=tree[now].value;//维护
    tree[now].top=topf;//初始化,链顶即为topf
    if(!tree[now].son)//没有重儿子就先不用便利了
    {
        return;
    }
    dfs(tree[now].son,topf);//优先遍历重儿子
    for(int i=head[now];i;i=tree[i].next)//在处理其他的情况
    {
        int v=tree[i].to;
        if(v==father||v==tree[now].son)//不能为自己的父亲节点,也不能为重儿子
        {
            continue;
        }
        dfs(v,v);//在轻儿子那里新开一条链
    }
} 

所以说两个dfs还是比较好理解的

关键的是在树链剖分里更好的套数据结构

欲知后事如何,请听下回分解!

蒟蒻浅谈树链剖分之一——两个dfs操作的更多相关文章

  1. 浅谈树链剖分 F&Q

    这是一篇迟来的博客,由于我懒得写文章,本篇以两个问题阐述笔者对树链剖分的初步理解. Q1:树链剖分解决什么问题? 树链剖分,就是把一棵树剖分成若干连续的链,将这些链里的数据映射在线性数组上维护.比方说 ...

  2. 浅谈树链剖分(C++、算法、树结构)

    关于数链剖分我在网上看到的有几个比较好的讲解,本篇主要是对AC代码的注释(感谢各位witer的提供) 这是讲解 http://www.cnblogs.com/kuangbin/archive/2013 ...

  3. 树链剖分求LCA

    树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...

  4. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  5. HDU 3966 (树链剖分+线段树)

    Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...

  6. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  7. Qtree3题解(树链剖分(伪)+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...

  8. Qtree3题解(树链剖分+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意 很易懂吧.. 题解 我的做法十分的暴力:树链剖分(伪)+线段树+ std :: set ...

  9. 树链剖分&dfs序

    树上问题 很多处理区间的问题(像是RMQ,区间修改).可以用线段树,树状数组,ST表这些数据结构来维护.但是如果将这些问题挪到了树上,就不能直接用这些数据结构来处理了.这时就用到了dfs序和树链剖分. ...

随机推荐

  1. 从零开始学安全(三十三)●Ununtu16 LMAP 环境搭建

    sudo apt-get update # 获取最新资源包 sudo apt-get upgrade # 本机软件全部更新 sudo apt-get dist-upgrade # 本机系统软件更新 安 ...

  2. WPF 视频教程+笔记

    视频  https://www.bilibili.com/video/av46071366/ 笔记  https://www.cnblogs.com/Time_1990/p/4015716.html

  3. [PHP] yield沟通函数循环内外

    1.yield是函数内外,循环内外沟通用的 , 当你的函数需要返回一个大数组 , 循环的时候需要遍历这个大数组时 , 并且需要多次遍历这个函数的返回值 , 这个是有用的 2.当我也是只需要在一次循环中 ...

  4. Mybaits之Mapper动态代理开发

    Mybaits之Mapper动态代理开发 开发规范: Mapper接口开发方法只需要程序员与Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法 ...

  5. java开发环境配置——JDK

    虽然网上有很多类似的文章了,第一次搭的时候也是看的网上的文章,但为了做个记录,自己也写一下,记录一下. 首先是先安装JDK,JDK下载可以直接去官网下载,地址:http://www.oracle.co ...

  6. Android 异步框架 RxJava2

    观察者模式的概念 RxJava是android的异步框架,官方介绍是可观测的序列,组成异步基于事件程序的库.特点是观察者模式,基于事件流的链式调用,随着异步操作调度过程复杂的情况下,程序逻辑也变得越来 ...

  7. Java实现栈数据结构

    栈(英语:stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型,其特殊之处在于只能允许在链表或数组的一端(称为堆栈顶端指针,英语:top)进行加入数据(英语:push)和输出数据 ...

  8. Prometheus Operator 架构 - 每天5分钟玩转 Docker 容器技术(178)

    本节讨论 Prometheus Operator 的架构.因为 Prometheus Operator 是基于 Prometheus 的,我们需要先了解一下 Prometheus. Prometheu ...

  9. Linux中逻辑卷的快照与还原

    有关逻辑卷的其他操作,请看: Linux中对逻辑卷的建立 Linux中对逻辑卷进行扩容与缩小 Linux中对逻辑卷的移除 LVM还有快照的功能,类似windows的系统还原点.其特点: 1.快照卷的容 ...

  10. Linux命令学习总结:ls

    命令简介: ls命令用来列出目标目录(缺省的话为当前目录)中所有的子目录和文件.指令英文原义:list 指令所在路径:/bin/ls 执行权限:All User 命令语法: ls [OPTION].. ...