• 洛谷 P3379 【模板】最近公共祖先(LCA,树链剖分)


    传送门


    解题思路

    求LCA一般可以用倍增、树链剖分、tarjan算法解决。

    这里只介绍树剖。

    先处理出每一条链的链顶,然后对于每两个要求的点,判断是否在同一条链上。如果在,那么深度较浅的点就是LCA。

    如果不在同一条链上,就比较两个所在链的链顶的深度,把链顶深度较低的点跳到链顶的父亲(这样就保证有答案了)。

    时间复杂度:O(mlogn)。

    AC代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cmath>
     4 #include<cstdio>
     5 #include<cstring>
     6 using namespace std;
     7 const int maxn=500005;
     8 int n,m,s,siz[maxn],cnt,tp[maxn],dep[maxn],p[maxn],son[maxn],f[maxn];
     9 struct node{
    10     int v,next;
    11 }e[maxn*2];
    12 void insert(int u,int v){
    13     cnt++;
    14     e[cnt].next=p[u];
    15     e[cnt].v=v;
    16     p[u]=cnt;
    17 }
    18 void dfs1(int u,int fa,int deep){
    19     int maxsize=0,maxson=0;
    20     f[u]=fa;
    21     siz[u]=1;
    22     dep[u]=deep;
    23     for(int i=p[u];i!=-1;i=e[i].next){
    24         int v=e[i].v;
    25         if(v==fa) continue;
    26         dfs1(v,u,deep+1);
    27         siz[u]+=siz[v];
    28         if(siz[v]>maxsize){
    29             maxsize=siz[v];
    30             maxson=v;
    31         }
    32     }
    33     son[u]=maxson;
    34 }
    35 void dfs2(int u,int fa,int top){
    36     tp[u]=top;
    37     if(son[u]){
    38         dfs2(son[u],u,top); 
    39         for(int i=p[u];i!=-1;i=e[i].next){
    40             int v=e[i].v;
    41             if(v==fa||v==son[u]) continue;
    42             dfs2(v,u,v);
    43         }
    44     }
    45 }
    46 int main()
    47 {
    48     memset(p,-1,sizeof(p));
    49     cin>>n>>m>>s;
    50     for(int i=1;i<n;i++){
    51         int u,v;
    52         scanf("%d%d",&u,&v);
    53         insert(u,v);
    54         insert(v,u);
    55     }
    56     dfs1(s,-1,1);
    57     dfs2(s,-1,s);
    58 //    for(int i=1;i<=n;i++) cout<<tp[i]<<" ";
    59     for(int i=1;i<=m;i++){
    60         int a,b;
    61         scanf("%d%d",&a,&b);
    62         while(tp[a]!=tp[b]){
    63             if(dep[tp[a]]>dep[tp[b]]) a=f[tp[a]];
    64             else b=f[tp[b]];
    65         }
    66         if(dep[a]>dep[b]) cout<<b<<endl;
    67         else cout<<a<<endl;
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    【转载】用opencv中的CvEM做GMM的训练
    关于OpenCV做图像处理内存释放的一些问题
    关于C++ vector的拷贝
    VS2015创建的C++程序在Debug模式下不能调试
    OpenCV中IplImage和Mat间的相互转换
    视频资源下载方法[download video resources]
    关于win10安装VisualSVN遇到的一个问题及解决办法
    win7启动出现蓝屏STOP: 0X0000007B
    CentOS下挂在NTFS分区
    硬盘类型和Linux的分区
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/13619804.html
Copyright © 2020-2023  润新知