AcWing3422. 左孩子右兄弟(树形DP)

对于一棵多叉树,我们可以通过 “左孩子右兄弟” 表示法,将其转化成一棵二叉树。

如果我们认为每个结点的子结点是无序的,那么得到的二叉树可能不唯一。

换句话说,每个结点可以选任意子结点作为左孩子,并按任意顺序连接右兄弟。

给定一棵包含 N 个结点的多叉树,结点从 1 至 N 编号,其中 1 号结点是根,每个结点的父结点的编号比自己的编号小。

请你计算其通过 “左孩子右兄弟” 表示法转化成的二叉树,高度最高是多少。

注:只有根结点这一个结点的树高度为 0。

例如如下的多叉树:

QQ截图20210426100551.png

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

QQ截图20210426100638.png

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

输入格式

输入的第一行包含一个整数 N。

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

输出格式

输出一个整数表示答案。

数据范围

对于 30% 的评测用例,1≤N≤20;
对于所有评测用例,1≤N≤105。

输入样例:

5
1
1
1
2

输出样例:

4


如果只看一个结点和它的儿子们的话,实际上结构是左-右-右-右...的样子,只需要把子树深度最大的儿子排在最右边即可,简单树上DFS搞定。考场上写了极其降智的贪心,果然不适合考试TAT
#include <bits/stdc++.h>
#define N 100005
#define M 200005
using namespace std;
int n, head[N], ver[2 * M], Next[2 * M], tot = 0;
int dp[N], cnt[N];
void add(int x, int y) {
	ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
void dfs(int x, int pre) {
	int maxx = 0;
	dp[x] = 1;
	for(int i = head[x]; i; i = Next[i]) {
		int y = ver[i];
		if(y == pre) continue;
		dfs(y, x);
		maxx = max(maxx, dp[y]);
	}
	dp[x] = cnt[x] + maxx;
}
int main() {
	memset(dp, 0, sizeof(dp));
	memset(cnt, 0, sizeof(cnt));
	cin >> n;
	for(int i = 2; i <= n; i++) {
		int fa;
		cin >> fa;
		add(fa, i);
		add(i, fa);
		cnt[fa]++;
	}
	dfs(1, 0);
	cout << dp[1];
	return 0;
}
posted @   脂环  阅读(1588)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-06-02 The XOR Largest Pair (01Trie)
2020-06-02 洛谷 P2580 于是他错误的点名开始了(Trie)
2020-06-02 AcWing 142. 前缀统计(Trie)
点击右上角即可分享
微信分享提示
主题色彩