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

    luogu P3379 【模板】最近公共祖先(LCA)

    最近公共祖先:是指在有根树中,找出某两个结点u和v最近的公共祖先。

    对于有根树T的两个结点u、v,运用二进制拆分

    1.将u,v中深度较深的那一个点向上走到和深度较浅的点

    2.两个点一起向上走,直到走到同一个点时 u, v 的爸爸相同,这个点就是u,v的最近公共祖先,记作LCA(u,v)

    p[ j ][ i ]  = 由编号 j 的点向上走 2^i 步到达点的编号

    状态转移公式

    p[j][i]=p[p[j][i-1]][i-1]

    向上走 2^i 步到达p[ j ][ i ]==先走2^(i-1)到达p[ j ][ i - 1 ]再走2^(i-1)到达p[p [ j ] [ i-1 ]] [ i-1 ]

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int n,m,s,k;
    const int maxn=500005*2;
    int head[maxn],to[maxn],nxt[maxn],dep[maxn],p[maxn][30];
    int log(int x)
    {
        int a=1,sum=0;
        while(x>=a)
        {
            a*=2;
            sum++;
        }
        return sum;
    }
    void add(int x,int y)
    {
        k++;
        nxt[k]=head[x];
        to[k]=y;
        head[x]=k;
    }
    void dfs(int x,int fa)
    {
        for(int i=head[x];i;i=nxt[i])
        {
            if(to[i]==fa) continue;
            dep[to[i]]=dep[x]+1;
            p[to[i]][0]=x;
            dfs(to[i],x);
        }
        return ;
    }
    void lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        for(int i=k;i>=0;i--)
        {
            if(dep[p[x][i]]>=dep[y]) x=p[x][i];
            if(dep[p[x][i]]==dep[y]) break;
        }
        if(x==y)
        {
            printf("%d
    ",x);
            return;
        }
        for(int i=k;i>=0;i--)
        {
            if(p[x][i]!=p[y][i])
            {
                x=p[x][i];
                y=p[y][i];
            }
        }
        printf("%d
    ",p[x][0]);
        return;
    }
    int main()
    {
        int a,b;
        scanf("%d%d%d",&n,&m,&s);
        dep[s]=1;
        p[s][0]=s;
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(s,0);
        k=log(n)/log(2)+1;
        for(int i=1;i<=k;i++)
            for(int j=1;j<=n;j++)
                p[j][i]=p[p[j][i-1]][i-1];
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            lca(a,b);
        }
        return 0;
    }
  • 相关阅读:
    1503: [NOI2004]郁闷的出纳员
    2049: [Sdoi2008]Cave 洞穴勘测
    2301: [HAOI2011]Problem b
    BZOJ 1923: [Sdoi2010]外星千足虫
    BZOJ 2115: [Wc2011] Xor
    POJ 1830 开关问题
    欧拉函数基础
    BZOJ 2186 沙拉公主的困惑
    POJ 1845
    逆元基础知识整理
  • 原文地址:https://www.cnblogs.com/QAQq/p/10306203.html
Copyright © 2011-2022 走看看