如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:
深度: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间距离。
输入输出样例
展开
题目描述
如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:
深度: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
思路记录:题目就是几个基础题叠加在一起,求树的深度,树的宽度,两节点的最近公共祖先
比较难一点的就是求树的公共祖先,看了很多题解才明白,被自己菜哭的一天,递归有时候确实很难理解
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include<bits/stdc++.h>
using namespace std;
int a[105][2];
int wid[105];
int maxdeep=0;
int ans[105];
int root1,root2,n;
void dfs(int deep,int root){
wid[deep]++;//当前深度的宽度加一
ans[root]=deep-1;//当前节点的深度
if(a[root][0]==0&&a[root][1]==0){
maxdeep=max(maxdeep,deep);//求最大深度
return ;
}
if(a[root][0]) dfs(deep+1,a[root][0]);
if(a[root][1]) dfs(deep+1,a[root][1]);
}
int lca(int root){ //找公共祖先,判断root节点又没有可能是公共祖先,这个算法等于复杂度O(n)
//每一次递归就是需要判断该节点的左节点和右节点是否满足条件
if( root == 0 || root == root1 || root == root2) return root;
int left = lca(a[root][0]);
int rigth = lca(a[root][1]);//根后序遍历相比差不多
if(left == 0 && rigth == 0) return 0;//该节点两个节点都不包含root1,root2
if(left == 0) return rigth;//右节点是,返回rigth给上一层
if(rigth == 0) return left;//左节点是,返回left 给上一层
return root;//左右节点都是,所以该节点就是公共祖先,直接返回
}
int main(){
int s1,s2;
cin>>n;
for(int i=0;i<n-1;i++){
cin>>s1>>s2;
if(a[s1][0]==0)
a[s1][0]=s2;
else a[s1][1]=s2;
}
cin>>root1>>root2;
dfs(1,1);
cout<<maxdeep<<endl;
int maxwid=0;
for(int i=0;i<105;i++)
maxwid=max(maxwid,wid[i]);
cout<<maxwid<<endl;
int lcaroot = lca(1);
cout<<ans[root1]*2+ans[root2]-3*ans[lcaroot]<<endl;
return 0;
}