# AT2291 题解

题目传送门 AT2291

建议在原 luogu blog 食用更佳!

# 题意简述

通过淘汰赛从 N 个人中选出一个冠军。

# 题目分析

小学的时候学奥数经常遇到这种类似球队比赛。我们小学画的那个树杈图不就是咱们现在的二叉树吗?

所以,我们只需要构造一个树,叶子节点为选手,非叶子节点为该比赛的胜出者,构造出这么一个最优解树。我们给他们编上号,然后开始比赛!

对于冠军一号选手来说,二四六号都要和他打一场,发现这三个人和一号打比赛的顺序变了,比赛的性质就变了啊(直接出现开局就一血)。发现一号要先跟子树高度小的比赛,再跟子树高度大的比赛,因为比赛时间越靠后,这颗子树就越靠近根。然后发现这个可以用递归。

题目给的是一个有根树,如果我们根据最优解树中每个点失败时的深度进行规律的探索,我们就可发现一些东西:

  • 若当前根节点的深度为 d,则它的第 i 个儿子的深度为 d+i ,儿子的顺序由子树的高度决定;
  • 深度优先搜索 dfs(1)

# 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<bits/stdc++.h>

using namespace std;

const int M=500005;

int N,Height[M];
vector<int> G[M];

bool cmp(int x,int y)
{
return Height[x]>Height[y];
}

void dfs(int u)
{
for(register int i=0;i<int(G[u].size());i++)
{
dfs(G[u][i]);
}

sort(G[u].begin(),G[u].end(),cmp);

for(register int i=0;i<int(G[u].size());i++)
{
Height[u]=max(Height[u],Height[G[u][i]]+i+1);
}
}
signed main(void)
{
cin>>N;

for(register int i=2;i<=N;i++)
{
int father;
cin>>father;
G[father].push_back(i);
}

dfs(1);
cout<<Height[1]<<endl;

return 0;
}
Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

spaceswalker WeChat Pay

WeChat Pay

spaceswalker Alipay

Alipay

spaceswalker PayPal

PayPal