题目来源:蓝桥杯2021初赛 C++ A组H题
题目描述
对于一棵多叉树,我们可以通过“左孩子右兄弟” 表示法,将其转化成一棵二叉树。
如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。
换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。
给定一棵包含N 个结点的多叉树,结点从1 至N 编号,其中1 号结点是根,每个结点的父结点的编号比自己的编号小。
请你计算其通过“左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。
注:只有根结点这一个结点的树高度为0 。
例如如下的多叉树:
可能有以下3 种(这里只列出3 种,并不是全部) 不同的“左孩子右兄弟”表示:
其中最后一种高度最高,为4。
输入格式
输入的第一行包含一个整数N。
以下N-1 行,每行包含一个整数,依次表示2 至N 号结点的父结点编号。
对于30% 的评测用例,1 ≤ N ≤ 20;
对于所有评测用例,1 ≤ N ≤ 100000。
输出格式
输出一个整数表示答案。
输入样例
5
1
1
1
2
输出样例
4
问题分析
选任意顺序将所有子节点中任选作为左结点,将该结点的兄弟结点依次在右侧连接,最后形成一个二叉树,使得二叉树高度最高。
以1为根结点。用vector来存储图。用DFS来计算高度。
还有一种解法是,用DP来实现。
AC的C++语言程序如下:
/* LQ0135 左孩子右兄弟 */
#include <iostream>
#include <vector>
using namespace std;
const int N = 100000 + 1;
vector<int> g[N];
int dfs(int k)
{
if (g[k].size()) {
int maxh = 0;
for (int i = 0; i < g[k].size(); i++)
maxh = max(maxh, dfs(g[k][i]));
return maxh + g[k].size();
} else
return 0;
}
int main()
{
int n, u;
cin >> n;
for (int v = 2; v <= n; v++) {
cin >> u;
g[u].push_back(v);
}
cout << dfs(1) << endl;
return 0;
}