• LCA 算法(二)倍增


     介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上。

     

    代码:

     

     1 //LCA:Doubly
     2 
     3 #include<cstdio>
     4 #define swap(a,b) a^=b^=a^=b
     5 #define maxn 500010
     6 using namespace std;
     7 
     8 int n,m,s,tot,head[maxn],deep[maxn],p[maxn][20];
     9 struct node
    10 {
    11     int nxt,to;
    12 }edge[maxn<<1];
    13 
    14 int read()
    15 {
    16     int x=0,f=1;
    17     char c=getchar();
    18     while (c<48||c>57)
    19         f=c=='-'?-1:1,c=getchar();
    20     while (c>=48&&c<=57)
    21         x=(x<<1)+(x<<3)+(c^48),c=getchar();
    22     return x*f;
    23 }
    24 
    25 void write(int x)
    26 {
    27     if (x<0)
    28         x=-x,putchar('-');
    29     if (x>=10)
    30         write(x/10);
    31     putchar(x%10+48);
    32 }
    33 
    34 void add(int a,int b)
    35 {
    36     edge[++tot]=(node){head[a],b};
    37     head[a]=tot;
    38     edge[++tot]=(node){head[b],a};
    39     head[b]=tot;
    40 }
    41 
    42 void init()
    43 {
    44     for (int j=1;(1<<j)<=n;j++)
    45         for (int i=1;i<=n;i++)
    46             if (p[i][j-1])
    47                 p[i][j]=p[p[i][j-1]][j-1];
    48 }
    49 
    50 int dfs(int u)
    51 {
    52     for (int i=head[u];i;i=edge[i].nxt)
    53         if (!deep[edge[i].to])
    54         {
    55             deep[edge[i].to]=deep[u]+1;
    56             p[edge[i].to][0]=u;
    57             dfs(edge[i].to);
    58         }
    59 }
    60 
    61 int LCA(int a,int b)
    62 {
    63     if (deep[a]<deep[b])
    64         swap(a,b);
    65     int i,j;
    66     for (i=0;(1<<i)<=deep[a];i++);
    67     i--;
    68     for (j=i;j>=0;j--)
    69         if (deep[b]<=deep[a]-(1<<j))
    70             a=p[a][j];
    71     if (a==b)
    72         return a;
    73     for (j=i;j>=0;j--)
    74         if (p[a][j]!=p[b][j]&&deep[p[a][j]]>=1)
    75         {
    76             a=p[a][j];
    77             b=p[b][j];
    78         }
    79     return p[a][0];
    80 }
    81 
    82 int main()
    83 {
    84     int i,j,k;
    85     n=read(),m=read(),s=read();
    86     for (i=1;i<=n-1;i++)
    87         add(read(),read());
    88     deep[s]=1;
    89     dfs(s);
    90     init();
    91     while (m--)
    92         write(LCA(read(),read())),putchar(10);
    93     return 0;
    94 }
  • 相关阅读:
    SQL查询
    SQL总结(二)连表查询
    SQL总结(一)基本查询
    SQL游标、函数的使用方法
    理解 Virtual DOM(摘)及评价
    virtual DOM的作用:将DOM的维护工作由系统维护转交给virtual DOM维护
    DOM的回流和重绘(重排、重绘)
    并发编程的核心
    执行流(指令流)的控制层级
    go语言的工资好高
  • 原文地址:https://www.cnblogs.com/Ronald-MOK1426/p/8999214.html
Copyright © 2020-2023  润新知