一.题目描述
如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:
- 深度:4
- 宽度:4
- 结点 8 和 6 之间的距离:8
- 结点 7 和 6 之间的距离:3
其中宽度表示二叉树上同一层最多的结点个数,节点 u, v 之间的距离表示从 u 到 v 的最短有向路径上向根节点的边数的两倍加上向叶节点的边数。
给定一颗以 1 号结点为根的二叉树,请求出其深度、宽度和两个指定节点 x, y之间的距离。
## 输入格式
第一行是一个整数,表示树的结点个数 n。
接下来 n - 1行,每行两个整数 u, v,表示树上存在一条连接 u, v 的边。
最后一行有两个整数 x, y,表示求 x, y 之间的距离。
## 输出格式
输出三行,每行一个整数,依次表示二叉树的深度、宽度和 x, y 之间的距离。
## 样例 #1
### 样例输入 #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
## 提示
对于全部的测试点,保证1≤u,v,x,y≤n≤100且给出的是一棵树。
二.解题思路
将本题分为三个模块 1.求最大深度 2.求最大宽度 3.求节点距离
模块①同时求最大深度和最大宽度(利用dfs)
首先构造二叉树
int q1, w;//分别为父节点,子节点
for (int i = 1; i < n; i++)
{
cin >> q1 >> w;
if (!a[q1].left)a[q1].left = w;//存左子节点
else a[q1].right = w;//若左子存在元素,则放右子
a[w].fath = q1;//存放子节点的父节点
}
套用上节dfs模版
a[1].steep = 1;//初始化步数。
调用dfs函数,进行深度搜索
void dfs(int t)
{
if (b[t])return;
b[t] = 1;
int le = a[t].left, ri = a[t].right, st = a[t].steep;
de = max(de, st);
wide[st]++;//对每个深度进行累加(如节点4,5,6和7,深度都为3,即深度为3的有4个)
if (le)
{
a[le].steep = st + 1;//子节点深度等于父节点+1
dfs(le);//子节点遍历
}
if (ri)
{
a[ri].steep = st + 1;
dfs(ri);
}
}
模块②利用bfs求距离
需要一个结构体存放节点位置,和距离
typedef struct poin {
int pot, str;
}tr;
定义一个该类型的队列queue<tr> q;
套用bfs模版:
memset(b, -1, sizeof(b));//遍历过的标记
tr sa = {x,0};//初始位置和距离
b[x] = 1;//标记初始位置
q.push(sa);
while (!q.empty())
{
sa = q.front();
q.pop();
if (sa.pot == y) //到达末位置,结束循环
{
cout << sa.str << endl;
break;
}
int l = a[sa.pot].left, r = a[sa.pot].right, f = a[sa.pot].fath, s = sa.str;
//以下,对该点子父节点进行遍历
if (r && b[r]!=1)
{
b[r] = 1;
q.push({ r,s + 1 });
}
if (l && b[l]!=1)
{
b[l] = 1;
q.push({ l,s + 1 });
}
if (f &&b[f]!=1)
{
b[f] = 1;
q.push({ f,s + 2 });
}
}
三.代码展示
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
struct poi {
int left, right, fath, steep;
}a[110];
typedef struct poin {
int pot, str;
}tr;
queue<tr> q;
int n, x, y;
int b[110];
int wide[110], de = 0, wi = 0;
void dfs(int t)
{
if (b[t])return;
b[t] = 1;
int le = a[t].left, ri = a[t].right, st = a[t].steep;
de = max(de, st);
wide[st]++;
if (le)
{
a[le].steep = st + 1;
dfs(le);
}
if (ri)
{
a[ri].steep = st + 1;
dfs(ri);
}
}
int main()
{
cin >> n;
int q1, w;
for (int i = 1; i < n; i++)
{
cin >> q1 >> w;
if (!a[q1].left)a[q1].left = w;
else a[q1].right = w;
a[w].fath = q1;
}cin >> x >> y;
a[1].steep = 1;
dfs(1);
for (int j = 1; j <= n; j++)wi = max(wi, wide[j]);
cout << de << endl << wi << endl;
memset(b, -1, sizeof(b));
tr sa = {x,0};
b[x] = 1;
q.push(sa);
while (!q.empty())
{
sa = q.front();
q.pop();
if (sa.pot == y)
{
cout << sa.str << endl;
break;
}
int l = a[sa.pot].left, r = a[sa.pot].right, f = a[sa.pot].fath, s = sa.str;
if (r && b[r]!=1)
{
b[r] = 1;
q.push({ r,s + 1 });
}
if (l && b[l]!=1)
{
b[l] = 1;
q.push({ l,s + 1 });
}
if (f &&b[f]!=1)
{
b[f] = 1;
q.push({ f,s + 2 });
}
}
return 0;
}