zoukankan      html  css  js  c++  java
  • 【模板】最近公共祖先(LCA)

    题目链接:https://www.luogu.org/problemnew/show/P3379

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define re register
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define P pair<int,int>
    const int N=5e5+10;
    const int mod=1e9+7;
    void read(int &a)
    {
        a=0;
        int d=1;
        char ch;
        while(ch=getchar(),ch>'9'||ch<'0')
            if(ch=='-')
                d=-1;
        a=ch-'0';
        while(ch=getchar(),ch>='0'&&ch<='9')
            a=a*10+ch-'0';
        a*=d;
    }
    void write(int x)
    {
        if(x<0)
            putchar(45),x=-x;
        if(x>9)
            write(x/10);
        putchar(x%10+'0');
    }
    int fa[N][20],head[N],num,dep[N],t;
    bool vis[N];
    struct note
    {
        int to,next;
    }edge[2*N];
    void add(int u,int v)
    {
        edge[++num].next=head[u];
        edge[num].to=v;
        head[u]=num;
    }
    void dfs(int u,int h)
    {
        dep[u]=h;
        for(re int i=1;i<=t;i++)
        {
            if((1<<i)>=h)
                break;
            fa[u][i]=fa[fa[u][i-1]][i-1];///倍增核心算法
        }
        for(re int i=head[u];i;i=edge[i].next)
        {
            if(!vis[edge[i].to])
            {
                vis[edge[i].to]=1;
                fa[edge[i].to][0]=u;
                dfs(edge[i].to,h+1);
            }
        }
    }
    int LCA(int a,int b)
    {
        if(dep[a]<dep[b])
            swap(a,b);
        int d=dep[a]-dep[b];
        for(re int i=0;i<=t;i++)
            if((1<<i)&d)///跑去d有1的位置,可以避免减多而导致的回溯
                a=fa[a][i];///跳去跟B同样的深度
        if(a==b)
            return b;
        for(re int i=t;i>=0;i--)
        {
            if(!dep[fa[a][i]])
                continue;
            if(fa[a][i]==fa[b][i])
                continue;
            else
                a=fa[a][i],b=fa[b][i];
        }
        return fa[a][0];
    }
    int main()
    {
        int n,m,k;
        read(n);
        read(m);
        read(k);
        t=1.0*log2(n)+0.5;///算优化常数
        for(re int i=0;i<n-1;i++)
        {
            int a,b;
            read(a);
            read(b);
            add(a,b);
            add(b,a);
        }
        vis[k]=1;
        fa[k][0]=k;
        dfs(k,1);
        while(m--)
        {
            int a,b;
            read(a);
            read(b);
            write(LCA(a,b));
            putchar('
    ');
        }
        return 0;
    }
  • 相关阅读:
    结对-贪吃蛇游戏结对编项目设计文档
    java基础语法day04
    java基础语法day03
    轻量化ViewController的几个小技巧
    __weak与__block修饰符的区别
    OC与Swift的主要区别
    copy与retain /深拷贝与浅拷贝
    如何理解MVC设计模式
    iOS常见加密方法
    关于RunLoop
  • 原文地址:https://www.cnblogs.com/acm1ruoji/p/10672900.html
Copyright © 2011-2022 走看看