zoukankan      html  css  js  c++  java
  • 【数据结构】浅谈倍增求LCA

    思路

    运用树上倍增法可以高效率地求出两点x,y的公共祖先LCA

    我们设f[x][k]表示x的2k辈祖先

    f[x][0]为x的父节点

    因为从x向根节点走2k 可以看成从x走2k-1步 再走2k-1

    所以对于1≤k≤logn 有f[x][k]=f[f[x][k-1]][k-1] (类似二分思想)

    预处理:

    因此我们可以对树进行遍历后得到所有f[x][0] 再计算出f数组的所有值

    求LCA:

    设dep[x]为x的深度 设dep[x]≥dep[y](否则 可以交换x和y)

    使用二进制拆分 把x和y调整到同一深度

    若此时x与y相等 则已经找到LCA

    若不相等 则x和y同时向上跳同一深度 直到他们的父节点相同 则他们的父节点就是LCA

     代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define maxn 500050
    #define INF 1e9+7
    int n,m,cnt,ans,a,b,k,x,y;
    int h[maxn],dep[maxn],f[maxn][30];
    struct Edge
    {
        int next;
        int to;
    }e[maxn<<1];
    void add(int u,int v)
    {
        e[++cnt].to=v;
        e[cnt].next=h[u];
        h[u]=cnt;
    }
    void deal(int u,int fa)
    {
        dep[u]=dep[fa]+1;//子节点深度等于父节点+1 
        for(int i=1;i<=21;i++)
        {
            f[u][i]=f[f[u][i-1]][i-1];//计算u的2^k辈祖先 
        }
        for(int i=h[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==fa) continue;//如果是父节点就退出 
            f[v][0]=u;//v是u的子节点 
            deal(v,u);
        }
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);//如果x的深度比y小 就交换 
        for(int i=21;i>=0;i--)//从大到小循环 先走大步 如果不行在走小步 
        {
            if(dep[f[x][i]]>=dep[y]) x=f[x][i];//当走完深度还是大于y 就走 
            if(x==y) return x;//当x=y时 找到LCA 
        }
        for(int i=21;i>=0;i--)//此时x和y已经在同一层了 
        {
            if(f[x][i]!=f[y][i])//如果往上走之后还没有到LCA 就往上走 
            {
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];//返回LCA 
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);//无向图 
        }
        deal(1,0);//预处理 
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
    }
  • 相关阅读:
    关于hibernate的实体类中有集合类型转化成JSON的工具类
    关于hibernate的实体类中有集合类型转化成JSON的工具类
    浏览器九宫格的简单实现
    小米1S MIUI V5刷回V4教程
    新婚常用祝贺词
    【转】spring3 MVC实战,手工搭建Spring3项目demo
    Java8的日期时间处理
    穷达自有天命 无事多读好书
    [oracle/sql]求员工表中每个部门里薪水最高的员工,那种sql最优?
    [Java]取得当前代码所在函数的函数名
  • 原文地址:https://www.cnblogs.com/BrokenString/p/9775540.html
Copyright © 2011-2022 走看看