zoukankan      html  css  js  c++  java
  • 黑科技——树剖两次dfs转一次dfs!

    黑科技——树剖两次(dfs)转一次(dfs)

    重所周知,树链剖分通常是要(dfs​)两次的,就像这样:

    int Fa[N],dep[N],Sz[N],son[N];
    void dfs1(int x,int pre){
        Fa[x]=pre,dep[x]=dep[pre]+1;
        Sz[x]=1;
        erep(i,G,x){
            int y=G.to[i];
            if(y==pre)continue;
            dfs(y,x);
            Sz[x]+=Sz[y];
            (Sz[y]>Sz[son[x]])&&(son[x]=y);
        }
    }
    int L[N],R[N],Id,top[N];
    void dfs2(int x,int tp){
        top[x]=tp;
        if(son[x])dfs2(son[x],tp);
        erep(i,G,x){
            int y=G.to[i];
            if(y==Fa[x]||y==son[x])continue;
            dfs2(y,y);
        }
    }
    

    但是在一些(n)比较大并且的卡常毒瘤题中,我们如果使用了两次(dfs)就有可能会出现(tle)的情况。

    在这时,若我们无法优化本质算法的情况下我们需要卡常。

    怎么卡呢?利用(dfs)序:

    代码如下:

    int Fa[N],dep[N],Sz[N],son[N],L[N],R[N],Id[N],cnt,top[N];
    void dfs1(int x,int pre){
        Fa[x]=pre,dep[x]=dep[pre]+1;
        Sz[x]=1,L[x]=++cnt,Id[cnt]=x;
        erep(i,G,x){
            int y=G.to[i];
            if(y==pre)continue;
            dfs(y,x);
            Sz[x]+=Sz[y];
            (Sz[y]>Sz[son[x]])&&(son[x]=y);
        }
        R[x]=cnt;
    }
    rep(i,1,n)top[Id[i]]=Id[i]==son[Fa[Id[i]]]?top[Fa[Id[i]]]:Id[i];
    

    就这样我们只用了一次(dfs)就完成了树剖的预处理操作。

    别小看这一个递归,他在(n)较大的情况下,可以快大概(1)倍。

  • 相关阅读:
    U盘安装Ubuntu 10.4 Server
    MySQL操作使用
    Fedora17安装MySQL及配置
    笔记:重构
    Java 并发之线程安全
    Java 并发之共享对象
    UTF8 与 UTF16 编码
    matplotlib 初使用
    用 ggplot2 在同一个图上画多条颜色不同的线
    完成情况(一)
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11825989.html
Copyright © 2011-2022 走看看