• dfs 序 欧拉序


    推荐博客 :https://www.cnblogs.com/stxy-ferryman/p/7741970.html

      DFS序其实就是一棵树顺次访问的结点的顺序,例如下面这棵树

    它的 dfs 序就是 A-B-D-E-G-C-F-H

    int key = 0;
    void dfs(int x, int fa){ dfs_[cnt++] = x; s[x] = ++key; for(int i = 0 ; i < ve[x].size(); i++){ int to = ve[x][i]; if (to == fa) continue; dfs(to, x); } //dfs_[cnt++] = x; e[x] = key; }

     我们这里的 dfs_[ ] 数组表示的就是这棵树的 dfs 序,s[ ] 与 e[ ] 数组表示的就是访问某个结点的时间顺序。

    借助 dfs序,我们可以将树的结点变成一维的数组的形式,观察上面的图,B的子树中的结点有DEG,其在 dfs序中也是连续的。因此可以通过时间戳很容易找到子树的开始时间和结束时间。

    可以发现作为子树的时间戳一定在其内部。

    通过这个dfs序我们还可以做很多事情,比如给你一颗 n 个结点的树,m 个操作,每次操作可以使某一棵子树全部加上或减去某一个值,问最后每个点的值是多少, 或某个子树的权值之和是多少?

    看到这里再想这个问题就很简单了,找到dfs序,利用差分,就可以实现 o(1)的修改了。

    二 、 欧拉序

    欧拉序,就是从根节点出发,按照dfs顺序在绕回到根节点,其有两种不同的写法

    ( 1 ) 

    int cnt = 1;
    void dfs(int x, int fa){
        dfs_[cnt++] = x;       
        for(int i = 0 ; i < ve[x].size(); i++){
            int to = ve[x][i];
            if (to == fa) continue; 
            dfs(to, x);
            dfs_[cnt++] = x; 
        }    
    }
    

     

     (2)

    int cnt = 1;
    void dfs(int x, int fa){
        dfs_[cnt++] = x;       
        for(int i = 0 ; i < ve[x].size(); i++){
            int to = ve[x][i];
            if (to == fa) continue; 
            dfs(to, x);
        }    
        dfs_[cnt++] = x;
    }
    

    这两种是比较常见的欧拉序的写法。

    那么欧拉序有什么用呢?

      还是上面提到的问题,我们会发现所有的字母都出现了两次,相同的两个字母之间表示以其为根的所有子树,注意这些点都是出现两次的。计算的时候同样是将差分的数组累加,最后除以2即可。

    东北日出西边雨 道是无情却有情
  • 相关阅读:
    我的openwrt学习笔记(四):OpenWrt源码下载
    算法系列之“汉若塔”
    尖峰在线Oracle OCM实战 --开创国内Dtrace先河!
    Android开发屏幕适配知识点
    【cocos2d-js官方文档】十九、Cocos2d-JS单文件引擎使用指引
    PHP重载
    作为一个在城市打拼的人。
    关于马云最帅的照片是哪一张?!你们感受下!哈哈哈哈!(10P)
    Banana PI (香蕉派) 安装 ubuntu-core-14 最小核心的操作步骤
    (转载)偏序集的Dilworth定理学习
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8846543.html
Copyright © 2020-2023  润新知