C3. Brain Network (hard)
Breaking news from zombie neurology! It turns out that – contrary to previous beliefs – every zombie isborn with a single brain, and only later it evolves into a complicated brain structure. In fact, whenever a zombie consumes a brain, a new brain appears in its nervous system and gets immediately connected to one of the already existing brains using a single brain connector. Researchers are now interested in monitoring the brain latency of a zombie. Your task is to write a program which, given a history of evolution of a zombie's nervous system, computes its brain latency at every stage.
The first line of the input contains one numbern – the number of brains in the final nervous system (2 ≤ n ≤ 200000). In the second line a history of zombie's nervous system evolution is given. For convenience, we number all the brains by 1, 2, ..., n in the same order as they appear in the nervous system (the zombie is born with a single brain, number1, and subsequently brains 2, 3, ..., n are added). The second line containsn - 1 space-separated numbers p2, p3, ..., pn, meaning that after a new braink is added to the system, it gets connected to a parent-brain.
Output n - 1 space-separated numbers – the brain latencies after the brain numberk is added, for k = 2, 3, ..., n.
6
1
2
2
1
5
1 2 2 3 4
题意:已知结点1,每次往树里加一个结点,结点的父结点是树中已经得到的结点,每加入一个结点,求一次树的直径。
题目链接:点我!
思路:每加入一个点a,比较a和原来树的直径两端点的距离与树直径大小,更新树的直径。求结点间距离需要用到lca,结点a与结点b的距离是=dep[a]+dep[b]-2*dep[lca(a,b)]。
详细见代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 2*1e5+100;
int dep[maxn];
int u,v; //记录树的直径的端点
int pa[20][maxn];
void Add(int a,int f) 加结点时所需的处理
{
pa[0][a]=f;
for(int i=0;i<18;i++)
{
if(pa[i][a]<0) pa[i+1][a]=-1;
else pa[i+1][a]=pa[i][pa[i][a]];
}
}
inline int lca(int a,int b)
{
int i;
if(dep[a]>dep[b]) swap(a,b);
for(i=0;i<18;i++)
if((dep[b]-dep[a])>>i&1)
{
b=pa[i][b];
}
if(a==b) return a;
for(i=17;i>=0;i--)
{
if(pa[i][a]!=pa[i][b])
{
a=pa[i][a];
b=pa[i][b];
}
}
return pa[0][a];
}
inline int dis(int a,int b) //a,b之间的距离
{
return dep[a]+dep[b]-2*dep[lca(a,b)];
}
int main()
{
int n;
scanf("%d",&n);
u=1;v=1;
Add(1,-1);
int a;
int dis_uv=0; //树的直径
for(int i=2;i<=n;i++)
{
scanf("%d",&a);
dep[i]=dep[a]+1;
Add(i,a);
int dis_iu=dis(i,u);
int dis_iv=dis(i,v);
if(dis_iu>dis_iv)
{
if(dis_iu>dis_uv)
{
v=i;
dis_uv=dis_iu;
}
}
else if(dis_iv>dis_uv)
{
u=i;
dis_uv=dis_iv;
}
printf("%d%s",dis_uv,i==n ? "\n":" ");
}
return 0;
}