• 关于树论【LCA树上倍增算法】


    补了一发LCA,表示这东西表面上好像简单,但是细节真挺多。

    我学的是树上倍增,倍增思想很有趣~~(爸爸的爸爸叫奶奶.偶不,爷爷)有一个跟st表非常类似的东西,f[i][j]表示j的第2^i的祖先,就是说f[0][x]是父亲,f[1][x]是爷爷,f[2][x]是高祖父(爷爷的爷爷),f[3][x]是远祖父(高祖父的高祖父)

    搞个事:

    按古制辈份分为自己,父亲、祖父、曾祖、高祖、天祖、烈祖、太祖、远祖、鼻祖。

    扯回来,这个就是倍增的思想,可以方便的实现O(logn)的LCA,现在让你在构图的时候搞好f数组,一点问题都没有了吧~

    然后怎么求LCA?首先,我们先让深度比较深的点往上跳,然后两个一起跳,直到跳到父亲相同。那我们跳的时候,就像二进制一样,可以一次跳2^i次方

    caioj1236:(赤裸裸的LCA)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct node
    {
        int x,y,next;
    }a[210000];int len,last[110000];
    void ins(int x,int y)
    {
        a[++len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    //f[i][j]表示j的第2^i的祖先
    int Bin[30],dep[110000],f[25][110000];
    void dfs(int x,int fa)//构树 
    {
        f[0][x]=fa;//x的2^0=1就是自己父亲 
        for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]];//倍增,爸爸的爸爸是爷爷 
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(y!=fa)
            {
                dep[y]=dep[x]+1;
                dfs(y,x);
            }
        }
    }
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y])swap(x,y);//让比较深的先往上跳 
        for(int i=20;i>=0;i--)//倒着,想象成二进制,比如要找第5个祖先,就变成101,从左往右把所有为一的跳一下 
            if(dep[x]-dep[y]>=Bin[i])x=f[i][x];
        if(x==y)return x;
        for(int i=20;i>=0;i--)//深度一样了,x和y一起跳
            if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y]){x=f[i][x];y=f[i][y];}
        return f[0][x];
    }
    int main()
    {
        Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;
        int n,m,x,y;
        scanf("%d%d",&n,&m);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ins(x,y);ins(y,x);
        }
        dep[1]=1;dfs(1,0);
        while(m--)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",LCA(x,y));
        }
        return 0;
    }
  • 相关阅读:
    linux一切皆文件之tcp socket描述符(三)
    linux一切皆文件之Unix domain socket描述符(二)
    linux一切皆文件之文件描述符(一)
    k8s之使用secret获取私有仓库镜像
    https、ssl、tls协议学习
    k8s网络之calico学习
    泛型的原理、应用、约束、缓存
    C#中Unity对象的注册方式与生命周期解析
    监听EF执行的sql语句及状态
    递归一个List<T>,可自己根据需要改造为通用型。
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/7598784.html
Copyright © 2020-2023  润新知