第十二届蓝桥杯真题-左孩 子右兄弟(dfs)

题目描述
对于一棵多叉树,我们可以通过 “左孩子右兄弟” 表示法,将其转化成一棵
二叉树。
如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。
给定一棵包含 N 个结点的多叉树,结点从 1 至 N 编号,其中 1 号结点是根,每个结点的父结点的编号比自己的编号小。请你计算其通过 “左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。注:只有根结点这一个结点的树高度为 0 。
例如如下的多叉树:

在这里插入图片描述

可能有以下 3 种 (这里只列出 3 种,并不是全部) 不同的 “左孩子右兄弟”
表示:
在这里插入图片描述

其中最后一种高度最高,为 4。

输入
输入的第一行包含一个整数 N。
以下 N 1 行,每行包含一个整数,依次表示 2 至 N 号结点的父结点编号。

输出
输出一个整数表示答案。

样例输入

5
1
1
1
2

样例输出

4

思路
一开始没有看懂这个题的意思,后来发现这个题应该是说把多叉树转化成2叉树的形式,多的兄弟节点就转化成子节点,然后求最高的高度。

第一想法就是把这颗树接成只有一个字节点的树,把其他的兄弟节点都连成子节点,那么对于这种方案,高度最高的子节点就应该连在最底下,使高度最大化,那么其他的子节点就只能贡献一层的高度了,所以我们使用dfs先求出每个节点的最大转化高度,然后以最高的子节点在最下,返回子节点数+最大子节点高度即可!

我们可以拿样例图的最后一个方案来解释,1号节点有3个子节点,其中2节点是最高的,那么把它放在最底下,所以3,4号子节点就只能本身可以充当一层高度,和它们的子节点无关,那么我们就可以返回1号子节点的个数3+最高的子节点高度2,又因为根节点的高度是0,所以减一得到正确答案

代码

#include "iostream"
#include "vector"
using namespace std;
const int N=100010;
vector<int> v[N];
int n,x;
int dfs(int u)
{
	if(v[u].size()==0) return 1;
	int res=0;
	for(int i=0;i<v[u].size();i++)
	{
		res=max(res,dfs(v[u][i])); //获取最大子节点的高度
	}
	return v[u].size()+res; //这里最高的子节点会被加2次,但是没有加根节点的高度,所以两者抵消
}
int main()
{
	cin>>n;
	for(int i=2;i<=n;i++)
	{
		cin>>x;
		v[x].push_back(i);
	}
	cout<<dfs(1)-1<<endl; //这里由于根节点没有高度,所以要减一了
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

indolence-阡陌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值