LCA模版(倍增)

细节

当前节点的 \(2^i\) 号祖先等于\(2^{i-1}\)号祖先的 \(2^{i-1}\)号祖先,加法原理

for(int i=1;(1<<i)<=dep[u];i++)
f[u][i]=f[f[u][i-1]][i-1];

常数优化,O(n)预处理以2为底x的对数,在n较小的时候接受

for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
struct edge
{
    int to,next;
}e[maxn<<1];
int head[maxn],f[maxn][30+5],lg[maxn],dep[maxn];
int size=0;
void init()
{
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
void addedge(int u,int v)
{
    e[++size].to=v;
    e[size].next=head[u];
    head[u]=size;
}
void dfs(int u,int fa)//处理每个点信息:深度,祖先。
{
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for(int i=1;(1<<i)<=dep[u];i++)
    f[u][i]=f[f[u][i-1]][i-1];
    for(int i=head[u];i;i=e[i].next)
    {
        int to=e[i].to;
        if(to==fa)continue;
        dfs(to,u);
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y])
    swap(x,y);
    while(dep[x]>dep[y])
    x=f[x][lg[dep[x]-dep[y]]];
    if(x==y)return x;
    for(int i=lg[dep[x]];i>=0;i--)
    if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
int main()
{
    //init();
    int n=read(),m=read(),s=read();
    for(int i=1;i<=n-1;i++)
    {
        int u=read(),v=read();
        addedge(u,v);
        addedge(v,u);
    }
    dfs(s,0);
    for(int i=1;i<=n;i++)
    lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        printf("%d\n",lca(x,y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/DriverBen/p/10460043.html