zoukankan      html  css  js  c++  java
  • 倍增算法2(树上倍增)

    还是基本的问题,求LCA。

    详情见:

    https://blog.csdn.net/saramanda/article/details/54963914

    讲得非常好了。

    fa[i][j]=fa[ fa[i][j-1] ][j-1]

    用文字叙述为:i的第2^j个父亲 是i的第2^(j-1)个父亲的第2^(j-1)个父亲。

    很有回溯的味道,实现也是用的回溯法(dfs),注意这里的第二维表示是i+2^j,而上一篇文章的是i+2^j-1。

    任何一个数换成二进制后,都能想到可由∑2x 表示,一个长区间便能用logn个小区间凑起来,知道了这个性质便能很好的理解代码。

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<vector>
     7 using namespace std;
     8 const int maxn = 100005;
     9 const int max0 = 25;
    10 int fa[maxn][max0+5]={0},dep[maxn];
    11 vector<int>vt[maxn];
    12 void dfs(int x)
    13 {    //更新x的st表 
    14     for(int i=1;i<=max0;i++) 
    15         if(fa[x][i-1])   
    16             {
    17             fa[x][i]=fa[fa[x][i-1]][i-1];
    18            
    19               }
    20         else break; 
    21         
    22     int l=vt[x].size();   
    23     for(int i=0;i<l;i++)
    24         {    int t=vt[x][i];
    25         
    26             if(t!=fa[x][0])     //无向图也行 
    27             {    
    28                 fa[t][0]=x;       
    29                 dep[t]=dep[x]+1;     
    30                 dfs(t);
    31             }
    32         }
    33 }
    34 
    35 int LCA(int u,int v)
    36 {    //对齐 
    37     if(dep[u]<dep[v])swap(u,v);  
    38     int delta=dep[u]-dep[v];  
    39   
    40     for(int x=0;x<=max0;x++) //倍增凑步数  
    41         if((1<<x)&delta)
    42             u=fa[u][x];
    43     if(u==v)return u;
    44     
    45    //同时向LCA跳跃 
    46     for(int x=max0;x>=0;x--)    //由大到小凑数 
    47         if(fa[u][x]!=fa[v][x])   //判断是否超过LCA 
    48         {
    49             u=fa[u][x];
    50             v=fa[v][x];
    51         }
    52         
    53     return fa[u][0];    
    54 }
    55 int ind[maxn];
    56 int main()
    57 {
    58     int n;
    59     cin>>n;
    60     
    61     for(int i=1;i<n;i++)
    62     {
    63         int x,y;
    64         cin>>x>>y;
    65         vt[x].push_back(y); //有向图 
    66         ind[y]++; //入度++ 
    67     }
    68     int i=1;
    69     
    70     for(;i<=n;i++)
    71     {
    72         if(ind[i]==0) break;
    73     }
    74     dfs(i);
    75     int m;
    76     cin>>m;
    77     while(m--)
    78     {
    79         int x,y;
    80         cin>>x>>y;
    81         cout<<LCA(x,y)<<endl;
    82     
    83     }
    84 }
    85  
  • 相关阅读:
    [MTG][介绍]企业消息处理平台
    [MYSQL][TIP]入门级命令
    [JWF][API] 显示当前所有用户信息
    五一去了五里河公园
    [UML][Feel]活动图的建立
    [JWF][DOC] COM Object Library Reference
    计算机网络操作系统历年试题
    embed标签的使用
    Android初体验D2
    ScrollJquery列表无间隙滚动
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/9258007.html
Copyright © 2011-2022 走看看