zoukankan      html  css  js  c++  java
  • 树链剖分

    •参考资料

      [1]:博客

      [2]:论文(提取码:r87c)

    •抛出问题

      给定一棵有 $n$ 个节点、带边权的树;

      现在要对树进行 $m$ 个操作,操作有2类:

      • 将节点 $a$ 到节点 $b$ 路径上所有边权的值都改为 $c$

      • 询问节点 $a$ 到节点 $b$ 路径上的最大边权值

    •问题的解

      树链剖分是指一种对树进行划分的算法,它先通过轻重边剖分(Heavy-Light Decomposition)将树分为多条链;

      保证每个点属于且只属于其中一条链,然后再通过数据结构(树状数组、SBT、SPLAY、线段树等)来维护每一条链。

      使用这种方法后,一般可以将修改和查询的复杂度降为 $O(logn)$。

    •树链剖分的方法

    • 将树中的边分为:重边和轻边

    • 定义 $size(x)$ 为以 $x$ 为根的子树的节点个数
    • 令 $v$ 为 $u$ 的儿子节点中 $size$ 值最大的节点,那么 $v$ 称为 $u$ 的重儿子,边 $(u,v)$ 被称为重边
    • 树中重边之外的边被称为轻边
    • 全部由重边构成的路径称为重链

      例如,图中有5条重链:

        1→3→6→10
        2→5→9
        4
        7
        8

      相关变量解释:

      • $siz[i]$ : 以结点 $i$ 为根的子树中结点的个数
      • $son[i]$ : 结点 $i$ 的重儿子
      • $dep[i]$ : 结点 $i$ 的深度,根的深度为 $0$
      • $top[i]$ : 结点 $i$所在重链的链首结点
      • $fa[i]$ : 结点$i$的父结点
      • $tid[i]$ : 在 $DFS$ 找重链的过程中为结点 $i$ 重新编的号码,每条重链上的结点编号是连续的
      • $rid[i]$ : 与 $tid$ 的作用正好相反,编号 $i$ 对应的节点编号

    •树链剖分的过程

    •  两次 $DFS$
    • 第一次 $DFS$ 找重边,顺便求出所有的 $siz[i],dep[i],fa[i],son[i]$
    • 第二次DFS将重边连成重链,顺便求出所有的 $top[i],tid[i],rid[i]$
     1 void DFS1(int u,int f,int depth)///第一遍DFS求出fa,dep,siz,son
     2 {
     3     fa[u]=f;
     4     siz[u]=1;
     5     dep[u]=depth;
     6     for(int i=head[u];~i;i=G[i].next)
     7     {
     8         int v=G[i].to;
     9         
    10         if(v == f)///此处是v == f才continue,在这儿出过错
    11             continue;
    12             
    13         DFS1(v,u,depth+1);
    14         
    15         siz[u] += siz[v];
    16         if(son[u] == -1 || siz[v] > siz[son[u]])///更新u的重儿子
    17             son[u]=v;
    18     }
    19 }
    DFS1
     1 void DFS2(int u,int anc,int &k)///第二遍DFS求出 tid,rid,top
     2 {
     3     top[u]=anc;
     4     tid[u]=++k;
     5     rid[k]=u;
     6     if(son[u] == -1)
     7         return ;
     8     DFS2(son[u],anc,k);
     9 
    10     for(int i=head[u];~i;i=G[i].next)
    11     {
    12         int v=G[i].to;
    13         if(v != son[u] && v != fa[u])
    14             DFS2(v,v,k);
    15     }
    16 }
    DFS2

      入门题:http://www.cnblogs.com/kuangbin/p/3253741.html

  • 相关阅读:
    现在的代码,贴一下
    2014年七月写过的代码,现在看来,还有待改进呀
    第一次做技术论坛发博文,不知道说点啥
    04-树6. Huffman Codes--优先队列(堆)在哈夫曼树与哈夫曼编码上的应用
    04-树5. File Transfer--并查集
    04-树4. Root of AVL Tree-平衡查找树AVL树的实现
    03-树3. Tree Traversals Again (25)将先序遍历和中序遍历转为后序遍历
    03-树2. List Leaves (25) 二叉树的层序遍历
    二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历
    最大子序列和问题之算法优化
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9711441.html
Copyright © 2011-2022 走看看