树剖求LCA

Orz

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 500010

using namespace std;

struct node
{
    int ed,nxt;
};
node edge[maxn<<1];
int n,m,first[maxn],cnt,root;
int dep[maxn],fa[maxn],top[maxn],rnk[maxn],son[maxn],siz[maxn],rnk_cnt;

inline void add_edge(int s,int e)
{
    ++cnt;
    edge[cnt].ed=e;
    edge[cnt].nxt=first[s];
    first[s]=cnt;
    return;
}

inline void dfs_1(int now,int pre)
{
    dep[now]=dep[pre]+1; fa[now]=pre; siz[now]=1;
    for(register int i=first[now];i;i=edge[i].nxt)
    {
        int e=edge[i].ed;
        if(e==fa[now]) continue;
        dfs_1(e,now);
        siz[now]+=siz[e];
        if(son[now]==-1||siz[e]>siz[son[now]]) son[now]=e;
    }
    return; 
}

inline void dfs_2(int now,int heavy_fa)
{
    top[now]=heavy_fa;
    if(son[now]==-1) return;
    else dfs_2(son[now],heavy_fa);
    for(register int i=first[now];i;i=edge[i].nxt)
    {
        int e=edge[i].ed;
        if(e!=fa[now]&&e!=son[now]) dfs_2(e,e);
    }
    return;
}

inline int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return x;
}

int main()
{
    scanf("%d%d%d",&n,&m,&root);
    for(register int i=1;i<=n-1;++i)
    {
        int s,e;
        scanf("%d%d",&s,&e);
        add_edge(s,e);
        add_edge(e,s);
    }
    memset(son,-1,sizeof(son));
    dfs_1(root,0);
    dfs_2(root,root);
    for(register int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d
",lca(x,y)); 
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Hoyoak/p/11813542.html