zoukankan      html  css  js  c++  java
  • LCA最近公共祖先——Tarjan模板

    LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

    Tarjan是一种离线算法,时间复杂度O(n+Q),Q表示询问次数,其中使用倍增法加速算法。

    首先dfs建立二叉树,并标记深度、父节点。

    在LCA函数中,交换x、y保证x深度最大,计算深度差,在进行有限次计算后,保持x、y深度一致,再次进行多次倍增,寻找到最近公共祖先

    最后计算节点距离差:deep[x]+deep[y]-deep[t]*2

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 
     5 const int MAXN=100000;
     6 struct Edge
     7 {
     8     int to,next;
     9 }E[MAXN];
    10 int node,head[MAXN];
    11 int deep[MAXN],fa[MAXN][20];
    12 bool vis[MAXN];
    13 int n,m,ans;
    14 int a[MAXN];
    15 
    16 void insert(int u,int v)
    17 {
    18     E[++node]=(Edge){v,head[u]};head[u]=node;
    19     E[++node]=(Edge){u,head[v]};head[v]=node;
    20 }
    21 
    22 void dfs(int x)
    23 {
    24     vis[x]=1;
    25     for(int i=1;i<=18;i++)
    26     {
    27         if(deep[x]<(1<<i)) break;
    28         fa[x][i]=fa[fa[x][i-1]][i-1];
    29     }
    30     for(int i=head[x];i;i=E[i].next)
    31     {
    32         if(vis[E[i].to]) continue;
    33         deep[E[i].to]=deep[x]+1;
    34         fa[E[i].to][0]=x;
    35         dfs(E[i].to);
    36     }
    37 }
    38 
    39 int lca(int x,int y)
    40 {
    41     if(deep[x]<deep[y]) swap(x,y);
    42     int d=deep[x]-deep[y];
    43     for(int i=0;i<=18;i++)
    44         if((1<<i)&d) x=fa[x][i];
    45     for(int i=18;i>=0;i--)
    46         if(fa[x][i]!=fa[y][i])
    47         {
    48             x=fa[x][i];
    49             y=fa[y][i];
    50         }
    51     if(x==y) return x;
    52     else return fa[x][0];
    53 }
    54 
    55 int dis(int x,int y)
    56 {
    57     int t=lca(x,y);
    58     return deep[x]+deep[y]-deep[t]*2;
    59 }
    60 
    61 int main()
    62 {
    63     scanf("%d",&n);
    64     for(int i=1;i<n;i++)
    65     {
    66         int x,y;
    67         scanf("%d%d",&x,&y);
    68         insert(x,y);
    69     }
    70     dfs(1);
    71     scanf("%d",&m);
    72     for(int i=1;i<=m;i++)
    73         scanf("%d",&a[i]);
    74     for(int i=1;i<m;i++)
    75         ans+=dis(a[i],a[i+1]);
    76     printf("%d",ans);
    77     return 0;
    78 }
  • 相关阅读:
    js自执行函数的几种不同写法的比较
    chrome浏览器font-size<12px无效解决办法
    清楚浮动的那些事
    css中font-family的中文字体
    雅虎34条军规
    Modernizr的介绍和使用
    手机也能拍大片
    响应式Web设计 – 布局
    JAVA基础-JDBC连接池
    JAVA基础-JDBC使用
  • 原文地址:https://www.cnblogs.com/InWILL/p/10655316.html
Copyright © 2011-2022 走看看