• LCA 倍增


    最近公共祖先

    对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,q;
     7 int cnt,head[500],r[500],deep[500],p[500][10];
     8 struct node{
     9     int v;
    10     int next;
    11 }s[500];
    12 
    13 void add(int u,int v){
    14     s[++cnt].v=v;
    15     s[cnt].next=head[u];
    16     head[u]=cnt;
    17 }
    18 
    19 void DFS(int x){//预处理深度 
    20     for(int i=head[x];i;i=s[i].next){
    21         int V=s[i].v;
    22         if(!deep[V]){
    23             deep[V]=deep[x]+1;
    24             p[V][0]=x;
    25             DFS(V);
    26         }
    27     }
    28 }
    29 
    30 void init(){//p[i][j]表示i的第2^j的祖先 
    31     for(int j=1;(1<<j)<=n;++j)
    32         for(int i=1;i<=n;++i)
    33             if(p[i][j-1]!=-1)
    34                 p[i][j]=p[p[i][j-1]][j-1];//i的2^j的祖先-->i的2^(j-1)的祖先的2^(j-1)的祖先 
    35 }
    36 
    37 int LCA(int a,int b){
    38     if(deep[a]<deep[b])swap(a,b);
    39     int i;
    40     for(i=0;(1<<i)<=deep[a];++i); 
    41     --i;
    42     for(int j=i;j>=0;--j)//使a,b在相同深度
    43         if(deep[a]-(1<<j)>=deep[b])a=p[a][j];
    44     if(a==b)return a;
    45     for(int j=i;j>=0;--j)//LCA 
    46         if(p[a][j]!=-1&&p[a][j]!=p[b][j]){
    47             a=p[a][j];
    48             b=p[b][j];
    49         }    
    50     return p[a][0];
    51 }
    52 
    53 int main(){
    54     scanf("%d",&n);
    55     for(int i=1;i<n;++i){
    56         int x,y;
    57         scanf("%d%d",&x,&y);
    58         ++r[y];
    59         add(x,y);
    60     }
    61     int rt;
    62     for(int i=1;i<=n;++i)if(r[i]==0){rt=i;break;}
    63     memset(p,-1,sizeof(p));
    64     p[rt][0]=rt;
    65     DFS(rt);
    66     init();
    67     
    68     scanf("%d",&q);
    69     for(int i=1;i<=q;++i){
    70         int x,y;
    71         scanf("%d%d",&x,&y);
    72         printf("%d
    ",LCA(x,y));
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    第10节--单行函数之数学函数
    第九节--单行函数之日期函数
    【译】什么是游戏开发实体系统框架(终)
    【译】什么是游戏开发实体系统框架(一)
    【译】游戏《实体系统框架》译文——序
    IDEA 快捷键
    Java学习笔记1
    Java面试题
    Java学习笔记——集合
    Java学习笔记——String类常用方法
  • 原文地址:https://www.cnblogs.com/wjting/p/6073278.html
Copyright © 2020-2023  润新知