HDOJ 4008-Parent and son解题报告

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

题意很简单,给出一棵树,找出以x节点为根节点的情况下,y节点的最小儿子节点和最小子孙节点,每次进行一次搜索肯定是不行的,所以我们考虑只进行一次搜索,利用得到的结论去找到在其他情况下的解,先在以1为根节点的树中进行一遍深度优先搜索,记录下son[u][0](以u为根节点的子树中标号最小的子节点点)son[u][1](以u为根节点的树中标号次小的子节点)因为在选定不同的根节点导致图旋转的过程中,这两个节点最多有一个会变成u的父节点,所以直接确定另一个就可以了。low[u][0](以u为节点的子树中,标号最小的子孙节点),low[u][1](以u为根的所有的子树中所有low[v][0]的次小值,注意仔细理解这句话的意义,因为图旋转的过程中最多会有一棵子树在u节点的上方,所以同样可以确定另一个),具体的有一些细节的实现可以看代码

View Code
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define N 100005
  5 #define inf 0x7fffffff
  6 using namespace std;
  7 int son[N][2],low[N][2];
  8 int pre[N];
  9 int head[N],cnt;
 10 struct node
 11 {
 12     int v,next;
 13 };
 14 node e[N*2];
 15 bool used[N];
 16 int min(int a,int b)
 17 {
 18     return a<b?a:b;
 19 }
 20 void add(int u,int v)
 21 {
 22     e[cnt].v=v,e[cnt].next=head[u],head[u]=cnt++;
 23     e[cnt].v=u,e[cnt].next=head[v],head[v]=cnt++;
 24 }
 25 void init()
 26 {
 27     memset(head,-1,sizeof(head));
 28     memset(pre,-1,sizeof(pre));
 29     memset(used,0,sizeof(used));
 30     cnt=0;
 31     int i;
 32     for(i=0;i<N;i++)
 33     {
 34         son[i][0]=son[i][1]=inf;
 35         low[i][0]=low[i][1]=inf;
 36     }
 37 }
 38 void dfs(int u,int f)
 39 {
 40     int i,v;
 41     pre[u]=f;
 42     used[u]=true;
 43     for(i=head[u];i>=0;i=e[i].next)
 44     {
 45         v=e[i].v;
 46         if(used[v])
 47         continue;
 48         if(v!=f)
 49         dfs(v,u);
 50         if(v<son[u][1])
 51         son[u][1]=v;
 52         if(son[u][0]>son[u][1])
 53         swap(son[u][0],son[u][1]);
 54         int minn=low[v][0]<v?low[v][0]:v;
 55         if(minn<low[u][1])
 56         low[u][1]=minn;
 57         if(low[u][1]<low[u][0])
 58         swap(low[u][1],low[u][0]);
 59     }
 60 }
 61 int find(int x,int y)
 62 {
 63     while(pre[x]!=x)
 64     {
 65         if(pre[x]==y)
 66         return x;
 67         x=pre[x];
 68     }
 69     return 0;
 70 }
 71 int main()
 72 {
 73     int t,n,x,y,q,ans1,ans2,temp,i;
 74     scanf("%d",&t);
 75     while(t--)
 76     {
 77         scanf("%d%d",&n,&q);
 78         init();
 79         for(i=1;i<n;i++)
 80         {
 81             scanf("%d%d",&x,&y);
 82             add(x,y);
 83         }
 84         dfs(1,1);
 85         for(i=1;i<=q;i++)
 86         {
 87             scanf("%d%d",&x,&y);
 88             ans1=ans2=inf;
 89             temp=find(x,y);
 90             if(temp==0)
 91             {
 92                 ans1=son[y][0];
 93                 ans2=low[y][0];
 94             }
 95             else
 96             {
 97                 if(y!=1)
 98                 {
 99                     if(temp==son[y][0])
100                     ans1=min(son[y][1],pre[y]);
101                     else
102                     ans1=min(son[y][0],pre[y]);
103                     ans2=1;//这个可以直接确定
104                 }
105                 else
106                 {
107                     if(temp==son[y][0])
108                     ans1=son[y][1];
109                     else
110                     ans1=son[y][0];
111                     if(low[temp][0]==low[y][0]||low[y][0]==temp)//选择最小值次小的那棵子树
112                     ans2=low[y][1];
113                     else
114                     ans2=low[y][0];
115                 }
116             }
117             if(ans1==inf||ans2==inf)
118             printf("no answers!\n");
119             else
120             printf("%d %d\n",ans1,ans2);
121         }
122         printf("\n");
123     }
124     return 0;
125 }

 

posted @ 2012-09-05 14:27  zhenhai  阅读(145)  评论(0编辑  收藏  举报