LCA——树链剖分

这里是我学习LCA的最后一种方法——树链剖分。

那么首先就先讲一下树链剖分是什么:

补充一下一些概念,下面会用:

  重儿子:一个节点的子节点中作为根节点的子树中节点最多的子节点。

  轻儿子:一个节点的子节点中除重儿子的子节点。

  链:起点为轻儿子或根节点,其余为重儿子的链。

树链剖分:顾名思义,将树剖成一条一条的链,要将树剖成链需要两个dfs。

  1.搜索求出每个节点的重儿子和父节点。

  2.根据节点的重儿子搜索出每一条链,记录节点的所在链和编号(链的起点越靠近根节点的编号越小,同一条链上越靠近起点的编号越小)。

下面求LCA:

若两个节点不在一条链上,将编号更大的那个更新(更新成它所在链的起点的父节点),直到他们在同一个链上时,编号更小的就是他们的最近公共祖先。

代码如下:

#include<iostream>
using namespace std;
int read(){
    int x=0,f=1;
    char a=getchar();
    while(a<'0'||a>'9'){
        if(a=='-')f=-1;
        a=getchar();
    }
    while(a>='0'&&a<='9'){
        x*=10;
        x+=a-'0';
        a=getchar();
    }
    return x*f;
}
int n,m,s;
int head[500010],tot;
int vis[500010],f[500010],sum[500010],zs[500010];
int dui[500010],id[500010],cnt;
struct node{
    int to;
    int nxt;
}edge[1000010];
void build(int u,int v){
    edge[++tot].to=v;
    edge[tot].nxt=head[u];
    head[u]=tot;
}
void dfs1(int u){
    sum[u]=1;
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(vis[v]==0){
            vis[v]=1;
            f[v]=u;
            dfs1(v);
            sum[u]+=sum[v];
            if(sum[v]>sum[zs[u]]){
                zs[u]=v;
            }
        }
    }
}
void dfs2(int u,int t){
    dui[u]=t;
    id[u]=++cnt;
    if(!zs[u])return ;
    dfs2(zs[u],t);
    for(int i=head[u];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v!=f[u]&&v!=zs[u]){
            dfs2(v,v);
        }
    }
}
int main(){
    n=read();m=read();s=read();
    for(int i=1;i<n;i++){
        int u,v;
        u=read();v=read();
        build(u,v);
        build(v,u);
    }
    vis[s]=1;
    f[s]=s;
    dfs1(s);
    dfs2(s,s);
    for(int i=1;i<=m;i++){
        int u,v;
        u=read();v=read();
        while(dui[u]!=dui[v]){
            if(id[u]>id[v]){
                u=dui[u];
                u=f[u];
            }
            else{
                v=dui[v];
                v=f[v];
            }
        }
        if(id[u]<id[v]){
            printf("%d\n",u);
        }
        else{
            printf("%d\n",v);
        }
    }
    return 0;
}

 

posted @ 2022-03-17 10:46  zzzzzz2  阅读(56)  评论(0编辑  收藏  举报