题目描述
如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:
深度:\(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
思路:对于第一个子问题,就是找树上最深的点,一遍\(dfs\)即可实现,对于第二个子问题,就是看看相同深度的点数目的最大值是多少,对于对三个子问题,就是通过\(LCA\)求两点间的树上距离。
代码:
#include<cstdio>
#include<algorithm>
#define maxn 107
using namespace std;
int f[maxn][7],n,x,y,js[maxn],maxx,head[maxn],num,d[maxn],zrj;
struct node {
int v,nxt;
}e[maxn<<1];
inline void ct(int u, int v) {
e[++num].v=v;
e[num].nxt=head[u];
head[u]=num;
}
void dfs(int u, int fa) {
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa) {
f[v][0]=u;
d[v]=d[u]+1;
maxx=max(maxx,d[v]);
dfs(v,u);
}
}
}
inline int lca(int a, int b) {
if(d[a]>d[b]) swap(a,b);
for(int i=6;i>=0;--i)
if(d[a]<=d[b]-(1<<i)) b=f[b][i];
if(a==b) return a;
for(int i=6;i>=0;--i)
if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
return f[a][0];
}
int main() {
scanf("%d",&n);
for(int i=1,u,v;i<n;++i) {
scanf("%d%d",&u,&v);
ct(u,v);ct(v,u);
}
dfs(1,0);
for(int i=1;i<=n;++i) js[d[i]]++;
for(int i=1;i<=maxx;++i) zrj=max(zrj,js[i]);
for(int j=1;j<=6;++j)
for(int i=1;i<=n;++i)
f[i][j]=f[f[i][j-1]][j-1];
scanf("%d%d",&x,&y);
printf("%d\n%d\n%d\n",maxx+1,zrj,(d[x]-d[lca(x,y)])*2-d[lca(x,y)]+d[y]);
return 0;
}