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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM