样例输入:
5
1
1
1
2
样例输出:
4
分析:根据左孩子兄弟表示法我们可以发现对于一个节点而言,他的所有孩子节点只有一个作为左孩子,其余所有的孩子节点都作为右孩子往下建树,那么根据贪心的思想肯定会选择一个可能深度最小的孩子节点作为左子树节点,而选一个可能深度最大的节点作为右子树最后的一个节点,那么我们就可以令f[i]记录以i为根的左孩子右兄弟的二叉树的最大高度,那么我们每次向下搜索,都选择一个可能构造深度最大的孩子节点来作为右孩子,假如当前节点有t个孩子节点,那么其中一个孩子节点作为左子树节点,其余t-1个都是作为右子树节点,深度直接增加t,而且在此基础上加上最大可能孩子节点的深度即可完成当前节点的更新,最后直接返回答案即可。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int f[N];//f[i]记录以i为根的左孩子右兄弟的二叉树的最大高度
vector<int> son[N];
int dfs(int x)
{
if(x!=1) f[x]=1;
for(int i=0;i<son[x].size();i++)
{
dfs(son[x][i]);
f[x]=max(f[x],f[son[x][i]]+(int)son[x].size());
}
return f[x];
}
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
{
int t;
scanf("%d",&t);
son[t].push_back(i);
}
printf("%d",dfs(1)-1);
return 0;
}