解法:树形dp+贪心
构建一棵树。对于每个选手
x
x
,若其被 选手打败,则在树中连边
(y,x)
(
y
,
x
)
。那么题目转化为将原多叉树转为二叉树(将一个点的兄弟变为其右儿子),要使二叉树的树高最小。
这。。贪心啊。。
设
fi
f
i
表示转为二叉树后以
i
i
为根的子树树高的最小值,那么有递推:
其中
j
j
表示 为
i
i
的第 个儿子(从
0
0
开始)
那么现在就是要安排每个儿子的顺序使得 最小。排序即可。
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> point[100001];
int n,fa,maxd[100001],ans;
bool cmp(int u,int v){return maxd[u]>maxd[v];}
void dfs(int u){
if(!point[u].size())maxd[u]=1;
for(int v:point[u])dfs(v);
sort(point[u].begin(),point[u].end(),cmp);
for(int i=0;i<point[u].size();++i)maxd[u]=max(maxd[point[u][i]]+i+1,maxd[u]);
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;++i)scanf("%d",&fa),point[fa].push_back(i);
dfs(1);
printf("%d",maxd[1]-1);
}