zoukankan      html  css  js  c++  java
  • 树链剖分求LCA

    树链剖分求LCA

    树链剖分需要将树的边分为重边和轻边。每个节点和他的儿子之间只能有一条重边,连接着该节点与他儿子中子树节点最大的一个。一系列连续起来的重边叫做重链,重链上的每个点的top值都是重链的顶端节点。

    用树链剖分来求LCA,就需要每次比较top_x与top_y的深度,将深度较大的点变为top_x的父节点。直到top_x=top_y,循环结束。两者之中深度较小的节点,就是这两个点的LCA。

    下附代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define N 42000
     4 using namespace std;
     5 int next[N],to[N],num,head[N],size[N],deep[N],father[N],top[N],n,m,p,a,b;
     6 void add(int false_from,int false_to){
     7     next[++num]=head[false_from];
     8     to[num]=false_to;
     9     head[false_from]=num;
    10 }
    11 void dfs1(int x){
    12     size[x]=1;
    13     deep[x]=deep[father[x]]+1;
    14     for(int i=head[x];i;i=next[i])
    15         if(father[x]!=to[i]){
    16             father[to[i]]=x;
    17             dfs1(to[i]);
    18             size[x]+=size[to[i]];
    19         }
    20 }
    21 void dfs2(int x){
    22     int mmax=0;
    23     if(!top[x])
    24         top[x]=x;
    25     for(int i=head[x];i;i=next[i])
    26         if(father[x]!=to[i]&&size[to[i]]>size[mmax])
    27             mmax=to[i];
    28     if(mmax){
    29         top[mmax]=top[x];
    30         dfs2(mmax);
    31     }
    32     for(int i=head[x];i;i=next[i])
    33         if(to[i]!=mmax&&father[x]!=to[i])
    34             dfs2(to[i]);
    35 }
    36 int lca(int x,int y){
    37     while(top[x]!=top[y]){
    38         if(deep[top[x]]<deep[top[y]])
    39             swap(x,y);
    40         x=father[top[x]];
    41     }
    42     if(deep[x]<deep[y])
    43         return x;
    44     return y;
    45 }
    46 int main(){
    47     scanf("%d%d%d",&n,&m,&p);
    48     for(int i=1;i<n;++i){
    49         scanf("%d%d",&a,&b);
    50         add(a,b);
    51         add(b,a);
    52     }
    53     dfs1(p);
    54     dfs2(p);
    55     for(int i=1;i<=m;++i){
    56         scanf("%d%d",&a,&b);
    57         printf("%d ",lca(a,b));
    58     }
    59     return 0;
    60 }
    View Code

     预处理复杂度:O(n)。

    一组询问复杂度:O(logn)。

    空间复杂度:O(n)。

    在线算法。

  • 相关阅读:
    全局变量 和 局部变量
    函数
    字符串拼接
    集合
    字典
    元祖
    列表
    Python 字符串 小练习
    ssm多数据源配置
    JAVA笔记:double四舍五入并保留两位小数的方法
  • 原文地址:https://www.cnblogs.com/jsawz/p/6814938.html
Copyright © 2011-2022 走看看