zoukankan      html  css  js  c++  java
  • 用rmq的思想做最近公共祖先的问题转化

    以poj 1330为例,因为这道题只是询问一次,还不至于使用st算法,只是在这里说一下怎么做问题的转化,在一个树的深搜过程中,每个点都会被访问到两次,这样形成了一个欧拉序列,假设两个点a,b的最近公共祖先是c那么在深搜的时候,按照顺序访问,如果要从a转到b那么必定会经过一次c节点,从c节点转到b所在的子树上,也就是说,c节点是这个从a到b的所有经过的节点之中,深度最小的一个,我们只需要在第一次出现a和第一次出现c的序列之间去找深度最小的即为其最近公共祖先。即为区间最值问题,rmq问题

    View Code
     1 #include<stdio.h>
     2 #include<string.h>
     3 #define N 10005
     4 int firs[2*N-1];
     5 int lis[2*N-1];
     6 int deep[2*N-1];
     7 int ti,t,head[N];
     8 int deg[N];
     9 struct edge
    10 {
    11     int v;
    12     int next;
    13 };
    14 edge e[N];
    15 void init()
    16 {
    17     memset(head,-1,sizeof(head));
    18     memset(firs,-1,sizeof(firs));
    19     memset(deg,0,sizeof(deg));
    20     ti=0;
    21     t=0;
    22 }
    23 void add(int u,int v)
    24 {
    25     e[t].v=v;
    26     e[t].next=head[u];
    27     head[u]=t++;
    28 }
    29 void dfs(int u,int de)
    30 {
    31     lis[ti]=u;
    32     deep[ti]=de;
    33     firs[u]=ti;
    34     ti++;
    35     int i,v;
    36     for(i=head[u];i>=0;i=e[i].next)
    37     {
    38         dfs(e[i].v,de+1);
    39         lis[ti]=u;
    40         deep[ti]=de;
    41         ti++;
    42     }
    43 }
    44 int main()
    45 {
    46     int n,i,j,a,b;
    47     int tc;
    48     scanf("%d",&tc);
    49     int min;
    50     while(tc--)
    51     {
    52         scanf("%d",&n);
    53         init();
    54         for(i=0;i<n-1;i++)
    55         {
    56             scanf("%d%d",&a,&b);
    57             add(a,b);
    58             deg[b]++;
    59         }
    60         for(i=1;i<=n;i++)
    61         if(!deg[i])
    62         break;
    63         dfs(i,0);
    64         /*for(i=0;i<2*n-1;i++)
    65         {
    66             printf("%d %d\n",lis[i],deep[i]);
    67         }*/
    68         scanf("%d%d",&a,&b);
    69         min=N+5;
    70         j=0;
    71         if(firs[a]>firs[b])
    72         {
    73             a^=b;
    74             b^=a;
    75             a^=b;
    76         }
    77         for(i=firs[a];i<=firs[b];i++)
    78         if(deep[i]<min)
    79         {
    80             min=deep[i];
    81             j=lis[i];
    82         }
    83         printf("%d\n",j);
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Python时间戳
    vux x-input 清除按钮不起作用
    MySQL连接查询流程源码
    Linux下用的脚本
    TableCache设置过小造成MyISAM频繁损坏 与 把table_cache适当调小mysql能更快地工作
    批量导入数据到InnoDB表速度优化
    DBA面对新mysql环境
    (进阶篇)PHP+Mysql+jQuery找回密码
    (进阶篇)PHP实现用户注册后邮箱验证,激活帐号
    (实用篇)php官方微信接口大全(微信支付、微信红包、微信摇一摇、微信小店)
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2497445.html
Copyright © 2011-2022 走看看