LCA 倍增

//LCA
//倍增 在线 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxn 500001
using namespace std;
int n,m,root,cnt;
int head[2*maxn],depth[maxn],f[maxn][21];//depth深度 f[a][b]指a节点的第2^b个祖先 
struct uio{
    int next,to;
}edge[2*maxn];
int add(int x,int y)
{
    edge[++cnt].next=head[x];
    edge[cnt].to=y;
    head[x]=cnt;
}
void dfs(int x)//求深度
{
    for(int i=head[x];i!=-1;i=edge[i].next)
        if(!depth[edge[i].to])
        {
            depth[edge[i].to]=depth[x]+1;
            f[edge[i].to][0]=x;
            dfs(edge[i].to);
        }
} 
int init()//初始化f数组 
{
    for(int i=1;(1<<i)<=n;i++)
        for(int j=1;j<=n;j++)
            f[j][i]=f[f[j][i-1]][i-1];
}
int lca(int x,int y)
{
    if(depth[x]<depth[y])
        swap(x,y);
    int d=depth[x]-depth[y];
    for(int i=0;(1<<i)<=d;i++)
        if((1<<i)&d)
//    for(int i=0;d;i++,d<<=1)//第二种写法 
//        if(d&1)
            x=f[x][i];
    if(x!=y)
    {
        for(int i=20;i>=0;i--)
            if(f[x][i]!=f[y][i])//f[x][i]==f[y][i] --> lca在此祖先下方或者是此祖先
                                //f[x][i]!=f[y][i] --> lca在此祖先上方 
                x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    else
        return x;  
} 
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&root);
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    } 
    depth[root]=1;
    dfs(root);
    init();
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        printf("%d\n",lca(u,v));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9280515.html