• Nearest Common Ancestors


    Nearest Common Ancestors

        题目大意:给你k组数据,每组数据输入一个树和一组询问,询问树上LCA。

        注释:n<=10000。

          想法:咳咳,我初学LCA,先来一道裸题压压惊。LCA?(Least Common Ancestors),是指最近公共祖先。最近公共祖先?是指他们的祖先中距离它们最近者。我们在此介绍一种方法:朴素法。记录一个根节点,由根节点起记录深度。对于一组询问x,y,不妨设deep[x]>deep[y]。显然,任意一个i使得deep[i]<deep[y]都一定不是x和y的LCA。所以,我们先将x移动到和y同样的深度。现在,x和y在同意深度,此时,我们想到,将x和y同时向上移动,知道x==y。这时朴素法求LCA,也是最简单的求LCA的方法。

        最后,附上丑陋的代码... ...

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define N 10010
     5 using namespace std;
     6 int fa[N],to[N],head[N],next[N];
     7 bool v[N];
     8 int deep[N];
     9 int tot;
    10 void add(int x,int y)//链式前向星加边
    11 {
    12     to[++tot]=y;
    13     next[tot]=head[x];
    14     head[x]=tot;
    15 }
    16 void dfs(int x,int pre,int step)//dfs处理深度和父亲节点
    17 {
    18     fa[x]=pre;deep[x]=step;
    19     for(int i=head[x];i;i=next[i]) dfs(to[i],x,step+1);
    20 }
    21 int lca(int x,int y)//求lca。
    22 {
    23     if(deep[x]<deep[y]) swap(x,y);
    24     while(deep[x]>deep[y]) x=fa[x];//将x移动到和y平齐
    25     while(x!=y) x=fa[x],y=fa[y];//两个点一起向上走
    26     return x;
    27 }
    28 int main()
    29 {
    30     int n;
    31     int cases;
    32     int a,b;
    33     int root;
    34     int x,y;
    35     scanf("%d",&cases);
    36     while(cases--)
    37     {
    38         tot=0;
    39         memset(v,false,sizeof(v));
    40         // memset(deep,0,sizeof(deep));
    41         memset(head,0,sizeof(head));//必须清
    42         // memset(fa,0,sizeof(fa));
    43         scanf("%d",&n);
    44         for(int i=1;i<n;i++)
    45         {
    46             scanf("%d%d",&a,&b);
    47             add(a,b);//加边
    48             v[b]=1;
    49         }
    50         for(int i=1;i<=n;i++)//我想直接处理出根节点,因为我加的是单向边
    51         {
    52             if(!v[i])
    53             {
    54                 root=i;
    55                 break;
    56             }
    57         }
    58         dfs(root,root,0);
    59         scanf("%d%d",&x,&y);
    60         printf("%d
    ",lca(x,y));
    61     }
    62     return 0;
    63 }

        小结:LCA是一个有意思的点,它包含了一些奇特的性质,在此先不做介绍。

          错误:1.清数组是只需要清tot和head[]数组。

             2.如果加的是单向边,必须预处理根节点。

        

  • 相关阅读:
    mvc+dwz准备工作
    C# action,delegate,func的用法和区别
    mvc+dwz第二天
    mvc+dwz第一天
    H5文件上传2
    H5文件上传1
    vs2010 nuget 基础连接已经关闭:发送时发生错误
    redis分布式锁
    C# 并发队列ConcurrentQueue
    正则表达式入门
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8295536.html
Copyright © 2020-2023  润新知