【LCA】洛谷P3379

倍增几大用处之一!!!LCA!!!

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const ll maxn=500010;
ll n,m,s,x,y,a,b,cnt=0,N;
ll f[maxn][30],head[maxn],dept[maxn];
struct Edge{
    ll next,to;
}cute[maxn<<1];//要建两遍图 数组不要忘记开大一倍

void build(ll x,ll y)
{
    cute[++cnt].next=head[x];
    cute[cnt].to=y;
    head[x]=cnt;
}

void pre()
{
    for(ll i=1;i<=N;i++)
        for(ll j=1;j<=n;j++)
            f[j][i]=f[f[j][i-1]][i-1];
}

void dfs(ll x)
{
    for(ll i=head[x];i;i=cute[i].next)
    {
        ll y=cute[i].to;
        if(f[x][0]!=y)
        {
            f[y][0]=x;
            dept[y]=dept[x]+1;
            dfs(y);
        }
    }
}

ll lca(ll x,ll y)
{
    if(dept[x]>dept[y]) swap(x,y);
    ll t=dept[y]-dept[x];
    for(ll i=N;i>=0;i--)
        if(t&(1<<i)) y=f[y][i];
    if(x==y) return x;
    for(ll i=N;i>=0;i--)
    {
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}

int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(ll i=1;i<=n-1;i++)
    {
        scanf("%lld%lld",&x,&y);
        build(x,y);
        build(y,x);
    }
    N=log2(n);
    dept[s]=1;
    f[s][0]=0;
    dfs(s);
    pre();
    for(ll i=1;i<=m;i++)
    {
        scanf("%lld%lld",&a,&b);
        printf("%lld
",lca(a,b));
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/Koiny/p/9883047.html