zoukankan      html  css  js  c++  java
  • HDU-4008 Parent and son

    题目:Parent and son

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4008

    题目大意:

      给你一棵树,编号从1-n,接下来m个询问,每个询问两个整数x、y,问你以x 作为这棵树的根,那么y 的儿子结点中编号最小的是什么,y 的后代中结点编号最小的又是哪个。

    题目思路:

      我们可以先以1 作为根来构建这棵树,每个结点保存:他的后代中最小编号的值minDown[],他的儿子结点中最小编号和次小编号的值minChild[][2]。查询中有可能遇到以下三种情况:

      1. x 不是 y 的后代,那么当它为根结点时,答案就是minChild[y][0]、minDown[y],这是最简单的一种情况。

      2. x 是 y 的后代,这种情况又可以分两种:

        (1). y 不等于 1 ,那么 x 为根时,y 的儿子中编号最小的就是 y 的父亲结点和{minChild[y][0]或minChild[y][1]}比较,选小的,不直接用minChild[y][0]的原因是有可能这个孩子是 x 的祖先,这样等 x 变为根时,这个结点就成了 y 的父亲。第二问:此时 y 后代中编号最小的肯定是 1 ,因为 1 此时是 y 的后代且 1 肯定最小。

        (2). y 等于 1,那么 x 为根时,y 的儿子中编号最小的也是minChild[y][0]和minChild[y][1]中选一个,第二问:后代编号最小的,可以预处理一下,遍历y 的所有儿子p,比较minDown[p]和p的大小,选小的,也像minChild[][]一样保存最小和次小,注意此时要保存次小和最小的p值,等会有用

      现在思路就清晰了,难点就在于黄色部分:怎么判断minChild[y][0]是不是x的祖先,要不要淘汰他!

      解决方法:当我们利用dfs 构建以 1 作为根的树时,可以做一个特殊处理,类似线段树,确定每一个结点的左边界和右边界,现在如果a 的左右边界包含在b 的左右边界里面,那么可以认为b 是a 的祖先。PS:这点很常见,但我还真没想到。。。

      细节自己小心。。。贴代码了

      

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #define Max 100010
      5 struct ENode
      6 {
      7   int ad;
      8   int next;
      9 };
     10 
     11 ENode en[2*Max];
     12 int eno;
     13 
     14 int head[Max];
     15 
     16 void Add(int a,int b)
     17 {
     18   en[eno].ad=b;
     19   en[eno].next=head[a];
     20   head[a]=eno;
     21   eno++;
     22 
     23   en[eno].ad=a;
     24   en[eno].next=head[b];
     25   head[b]=eno;
     26   eno++;
     27 }
     28 
     29 int minChild[Max][2];
     30 int minDown[Max];
     31 int l[Max],r[Max];
     32 int time;
     33 int fa[Max];
     34 int n,m;
     35 
     36 int min(int a,int b)
     37 {
     38   return a<b?a:b;
     39 }
     40 
     41 void dfs(int root)
     42 {
     43   l[root]=time++;
     44   minChild[root][0]=minChild[root][1]=minDown[root]=n+1;
     45   for(int i=head[root];i!=-1;i=en[i].next)
     46   {
     47     int v=en[i].ad;
     48     if(l[v]==0)
     49     {
     50       fa[v]=root;
     51       if(minChild[root][0]>v)
     52       {
     53         minChild[root][1]=minChild[root][0];
     54         minChild[root][0]=v;
     55       }
     56       else if(minChild[root][1]>v) minChild[root][1]=v;
     57       dfs(v);
     58       minDown[root]=min(minDown[root],minDown[v]);
     59     }
     60   }
     61   minDown[root]=min(minDown[root],minChild[root][0]);
     62   r[root]=time++;
     63 }
     64 
     65 bool isDown(int x,int y)
     66 {
     67   return l[x]>=l[y]&&r[x]<=r[y];
     68 }
     69 
     70 int main()
     71 {
     72   int t,a,b;
     73   scanf("%d",&t);
     74   while(t--)
     75   {
     76     scanf("%d%d",&n,&m);
     77     time=1;
     78     eno=0;
     79     for(int i=1;i<=n;i++)
     80       head[i]=-1;
     81     for(int i=1;i<n;i++)
     82     {
     83       scanf("%d%d",&a,&b);
     84       Add(a,b);
     85     }
     86     memset(l,0,sizeof(l));
     87     memset(r,0,sizeof(r));
     88     dfs(1);
     89     int min1=n+1,min2=n+1,son1=n+1,son2=n+1;
     90     for(int i=head[1];i!=-1;i=en[i].next)
     91     {
     92       int v=en[i].ad;
     93       int mi=min(v,minDown[v]);
     94       if(mi<min1)
     95       {
     96         min2=min1;
     97         son2=son1;
     98         min1=mi;
     99         son1=v;
    100       }
    101       else if(mi<min2)
    102       {
    103         min2=mi;
    104         son2=v;
    105       }
    106     }
    107 
    108     for(int i=0;i<m;i++)
    109     {
    110       int ans1,ans2;
    111       scanf("%d%d",&a,&b);
    112       if(b==1)
    113       {
    114         if(isDown(a,minChild[b][0]))
    115         {
    116           ans1=minChild[b][1];
    117         }
    118         else ans1=minChild[b][0];
    119         if(isDown(a,son1))
    120         {
    121           ans2=min2;
    122         }
    123         else ans2=min1;
    124       }
    125       else
    126       {
    127         if(isDown(a,b))
    128         {
    129           ans1=isDown(a,minChild[b][0])?minChild[b][1]:minChild[b][0];
    130           ans1=min(fa[b],ans1);
    131           ans2=1;
    132         }
    133         else
    134         {
    135           ans1=minChild[b][0];
    136           ans2=minDown[b];
    137         }
    138       }
    139       if(ans1==n+1 || ans2==n+1)
    140       {
    141         printf("no answers!
    ");
    142       }
    143       else printf("%d %d
    ",ans1,ans2);
    144     }
    145     printf("
    ");
    146   }
    147   return 0;
    148 }
  • 相关阅读:
    数据结构2_java---栈,括号匹配
    数据结构1_java---单链表的操作,约瑟夫问题
    算法---ALGO-3 Java K好数 蓝桥杯
    算法---区间K大数查找 Java 蓝桥杯ALGO-1
    算法---进制转换,八进制,十六进制,二进制
    实用---java保留小数点后位数以及输出反转数字
    实用---生命游戏 Java
    实用---GUI的搭建,windowbuilder的使用
    如今大火的算法框架TensorFlow,都有哪些值得一看的好书呢?
    如今大火的算法框架TensorFlow,都有哪些值得一看的好书呢?
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5413964.html
Copyright © 2011-2022 走看看