zoukankan      html  css  js  c++  java
  • P3379 【模板】最近公共祖先(LCA)

    --------------------------------

    链接:P3379 【模板】最近公共祖先(LCA)

    --------------------------------

    这道题我们要用到一种很神奇的东西,倍增。

    首先,我们考虑一下最简单的做法,记录深度。然后先让询问的x,y中深度大的点往上爬,直到两个点深度一样结束。

    然后两个点同时开始爬,当两个点相等时,就一定是公共祖先了

    --------------------------------

    但是一个一个爬太慢了,怎么办呢?

    我们就会用到一个东西,倍增。

    每次增加2^k幂

    --------------------------------

    没听懂?何不看看代码。

    其中depth表示深度。

    f[i][j]表示从i向上爬2^j后的祖先节点。

    -----------------------------------

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn= 2*500001; 
     5 struct kkk{
     6     int t;
     7     int next;
     8 }b[maxn];
     9 int depth[maxn],fa[maxn][22],logg[maxn],head[maxn];
    10 int cnt;
    11 int add(int x,int y){
    12     cnt++;
    13     b[cnt].t=y;
    14     b[cnt].next=head[x];
    15     head[x]=cnt;
    16 }
    17 void dfs(int f,int fath){//预处理 
    18     depth[f]=depth[fath]+1;
    19     fa[f][0]=fath;
    20     for(int i=1;(1<<i)<=depth[f];i++){//因为深度有限。所以往上爬也有限 
    21         fa[f][i]=fa[fa[f][i-1]][i-1];
    22     }
    23     for(int i=head[f];i;i=b[i].next){
    24         if(b[i].t!=fath)
    25             dfs(b[i].t,f);//遍历儿子们 
    26     }
    27 }
    28 int lca(int x,int y){
    29     if(depth[x]<depth[y])
    30     swap(x,y);
    31     while(depth[x]>depth[y])//首先让深度相同 
    32     x=fa[x][logg[depth[x]-depth[y]]-1];
    33     if(x==y)
    34         return x;//特别的 
    35     for(int k=logg[depth[x]]-1;k>=0;k--)//倍增算法 
    36             if(fa[x][k]!=fa[y][k])
    37                 x=fa[x][k],y=fa[y][k];
    38     return fa[x][0];
    39 }
    40 int n,m,s;
    41 int main(){
    42     scanf("%d%d%d",&n,&m,&s);
    43     for(int i=1;i<=n-1;++i){
    44         int x,y;
    45         scanf("%d%d",&x,&y);
    46         add(x,y);
    47         add(y,x);
    48     }
    49     dfs(s,0);
    50     for(int i=1;i<=n;++i)
    51         logg[i]=logg[i-1]+(1<<logg[i-1]==i);
    52         for(int i=1;i<=m;++i)
    53         {
    54             int x,y;
    55             scanf("%d%d",&x,&y);
    56             printf("%d
    ",lca(x,y));
    57         }
    58     return 0;
    59 }
    Ac
  • 相关阅读:
    实验一报告 20135238&20135207
    第十周
    极客Web前端开发资源大荟萃#022
    一个不错的编程小挑战 没事的时候可以试试
    变形金刚的能量方块(含代码)
    Angular控制器之间的数据通信
    使用HTML5本地 Drag和Drop API(native API)
    用requestAnimationFrame优化你的javascript动画
    模板字符串
    ES6的全新特性:模板字符串
  • 原文地址:https://www.cnblogs.com/For-Miku/p/11257972.html
Copyright © 2011-2022 走看看