题目链接
https://agc009.contest.atcoder.jp/tasks/agc009_b
题意简述
一场锦标赛有 n n n个人参加,第 1 1 1个人是冠军,其他每个人都记录了打败他的人的编号 a i a_i ai,求锦标赛至少进行了多少轮,这个锦标赛可能是不公平的,就是每个人参加的轮数可能不一样,以轮数最多的为准。
题解
对于每个点,他的每个子树sort一遍,最深的最晚打,第二深的第二晚……类似这样做tree dp。时间复杂度显然 O ( n log n ) O(n\log n) O(nlogn)。
代码
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=100000;
int n,pre[maxn*2+10],now[maxn+10],son[maxn*2+10],tot,f[maxn+10],tmp[maxn+10];
int ins(int a,int b)
{
pre[++tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int search(int u,int fa)
{
int cnt=0;
for(int i=now[u]; i; i=pre[i])
{
int v=son[i];
if(v==fa)
{
continue;
}
search(v,u);
}
for(int i=now[u]; i; i=pre[i])
{
int v=son[i];
if(v==fa)
{
continue;
}
tmp[++cnt]=f[v];
}
std::sort(tmp+1,tmp+cnt+1);
for(int i=cnt; i; --i)
{
f[u]=std::max(f[u],tmp[i]+cnt-i+1);
}
return 0;
}
int main()
{
n=read();
for(int i=2; i<=n; ++i)
{
int a=read();
ins(a,i);
ins(i,a);
}
search(1,0);
printf("%d\n",f[1]);
return 0;
}