洛谷P3884 [JLOI2009]二叉树问题

Posted MN2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3884 [JLOI2009]二叉树问题相关的知识,希望对你有一定的参考价值。

题目描述

如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:

深度:4 宽度:4(同一层最多结点个数)

结点间距离: ⑧→⑥为8 (3×2+2=8)

⑥→⑦为3 (1×2+1=3)

注:结点间距离的定义:由结点向根方向(上行方向)时的边数×2,

与由根向叶结点方向(下行方向)时的边数之和。

 

输入输出格式

输入格式:

输入文件第一行为一个整数n(1≤n≤100),表示二叉树结点个数。接下来的n-1行,表示从结点x到结点y(约定根结点为1),最后一行两个整数u、v,表示求从结点u到结点v的距离。

输出格式:

三个数,每个数占一行,依次表示给定二叉树的深度、宽度及结点u到结点v间距离。

输入输出样例

输入样例#1

10                               

1 2                           

1 3                            

2 4

2 5

3 6

3 7

5 8

5 9

6 10

8 6

输出样例#1

4

4

8

 

算法:

最近公共祖先(LCA)倍增

 

分析:

看题看了很久都没看懂,后来才发现这个是一个几乎lca的模板问题,只用把路径处理一下就好了,这里采用倍增的算法。

 

上代码:

 

 

 1 #include<cstdio>
 2 #define max(a,b) a>b?a:b
 3 #define swap(a,b) a^=b^=a^=b
 4 #define maxn 110
 5 using namespace std;
 6 
 7 int n,m,s,tot,head[maxn],deep[maxn],p[maxn][20],md,t[10],ans;
 8 struct node
 9 {
10     int nxt,to;
11 }edge[maxn<<1];
12 
13 int read()
14 {
15     int x=0,f=1;
16     char c=getchar();
17     while (c<48||c>57)
18         f=c==-?-1:1,c=getchar();
19     while (c>=48&&c<=57)
20         x=(x<<1)+(x<<3)+(c^48),c=getchar();
21     return x*f;
22 }
23 
24 void add(int a,int b)
25 {
26     edge[++tot]=(node){head[a],b};
27     head[a]=tot;
28     edge[++tot]=(node){head[b],a};
29     head[b]=tot;
30 }
31 
32 void init()
33 {
34     for (int j=1;(1<<j)<=n;j++)
35         for (int i=1;i<=n;i++)
36             if (p[i][j-1])
37                 p[i][j]=p[p[i][j-1]][j-1];
38 }
39 
40 int dfs(int u)
41 {
42     for (int i=head[u];i;i=edge[i].nxt)
43         if (!deep[edge[i].to])
44         {
45             deep[edge[i].to]=deep[u]+1;
46             p[edge[i].to][0]=u;
47             dfs(edge[i].to);
48         }
49 }
50 
51 int LCA(int a,int b)
52 {
53     if (deep[a]<deep[b])
54         swap(a,b);
55     int i,j;
56     for (i=0;(1<<i)<=deep[a];i++);
57     i--;
58     for (j=i;j>=0;j--)
59         if (deep[b]<=deep[a]-(1<<j))
60             a=p[a][j];
61     if (a==b)
62         return a;
63     for (j=i;j>=0;j--)
64         if (p[a][j]!=p[b][j]&&deep[p[a][j]]>=1)
65         {
66             a=p[a][j];
67             b=p[b][j];
68         }
69     return p[a][0];
70 }
71 
72 int main()
73 {
74     int i,j,k,u,v;
75     n=read();
76     for (i=1;i<=n-1;i++)
77         add(read(),read());
78     u=read(),v=read();
79     deep[1]=1;
80     dfs(1);
81     init();
82     for (i=1;i<=n;i++)
83         md=max(md,deep[i]),t[deep[i]]++;
84     for (i=1;i<=9;i++)
85         t[0]=max(t[0],t[i]);
86     k=LCA(u,v);
87     ans=(deep[u]-deep[k])*2+deep[v]-deep[k];
88     printf("%d\n%d\n%d",md,t[0],ans);
89     return 0;
90 }

 

以上是关于洛谷P3884 [JLOI2009]二叉树问题的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3884 [JLOI2009]二叉树问题 题解

二叉树入门(洛谷P1305)

洛谷 P1305 新二叉树 Label:字符串的输出总是有惊喜

洛谷 P1305 新二叉树

洛谷 P1229遍历问题

小L 的二叉树(洛谷 U4727)