zoukankan      html  css  js  c++  java
  • 树剖 lca

    GeneralLiu

        橙边为轻边

      红边为重边

      绿数为每个点的 top

      橙数为每个点的编号

    步骤

    1  先预处理 每个点的 deep深度  size子树大小  dad父节点  

    2  再预处理 每个点的 top重链顶点

    3  就是跳了

    应用

    洛谷 P2912 [USACO08OCT] 牧场散步

    效率蛮高的

    此题中用 len[i] 表示 i 到根距离

    询问 x 和 y 的距离

    答案可用 len[x] + len[y] - 2*len[ lca(x,y) ]表示

    而 lca 可以用树剖求出

    len[] 在树剖求lca 的预处理中 可以顺带求出来

    树剖求 lca 虽然不常用

    但它确实很吊

    嘻嘻 我的 树剖代码 目前是本题 的 rank1

    时间短 空间小

    #include<bits/stdc++.h>
    #define N 1003
    using namespace std;
    int cnt,head[N],to[N<<1],dis[N<<1],next[N<<1],len[N],size[N],deep[N],dad[N],n,m,top[N];
    int read(){//读入优化 
        char ch=getchar();
        int ans=0;
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){
            ans=ans*10+ch-'0';
            ch=getchar();
        }
        return ans;
    }
    int lca(int x,int y){//树剖求lca
        for(;top[x]!=top[y];){
            if(deep[top[x]]<deep[top[y]])x^=y^=x^=y;//利用二进制的 swap() 
            x=dad[top[x]];
        }
        if(deep[x]>deep[y])x^=y^=x^=y;
        return x;
    }
    void dfs(int k){//步骤1
        int v;
        size[k]=1,deep[k]=deep[dad[k]]+1;
        for(int i=head[k];i;i=next[i]){
            v=to[i];
            if(v!=dad[k])//各种预处理,包括针对本题的 len[]数组 
                len[v]=dis[i]+len[k],dad[v]=k,dfs(v),size[k]+=size[v];
        }
    }
          
    void dfs1(int k){//步骤2
        int t=0,v;
        if(!top[k])top[k]=k;
        for(int i=head[k];i;i=next[i]){
            v=to[i];
            if(v!=dad[k]&&size[t]<size[v])
                t=v;
        }
        if(t)top[t]=top[k],dfs1(t);
        for(int i=head[k];i;i=next[i]){
            v=to[i];
            if(v!=dad[k]&&v!=t)
                dfs1(v);
        }   
    }
    int main(){
        n=read(),m=read();
        int x,y,z;
        while(--n){
            x=read(),y=read(),z=read();
            next[++cnt]=head[x];
            to[cnt]=y;
            head[x]=cnt;
            dis[cnt]=z;
            next[++cnt]=head[y];
            to[cnt]=x;
            head[y]=cnt;
            dis[cnt]=z;
        }
        dfs(1);
        dfs1(1);
        while(m--){
            x=read(),y=read();
            printf("%d
    ",len[x]+len[y]-(len[lca(x,y)]<<1));
        }
        return 0;
    }
  • 相关阅读:
    leetcode -- Add Binary
    leetcode -- 4sum
    leecode -- 3sum Closet
    C++单例模式
    MapReduce的模式、算法和用例
    react 学习笔记
    css3 文字过长用...代替
    scss/css 中添加ie hack
    springmvc 解决跨域CORS
    springmvc 添加Junit4
  • 原文地址:https://www.cnblogs.com/1227xq/p/6813288.html
Copyright © 2011-2022 走看看