【题目描述】
【输入格式】
【输出格式】
【输入样例1】
7
1 2 1 1 4 4
【输入样例2】
12
1 1 2 2 4 4 3 3 1 10 8
【输出样例1】
1.0 4.0 5.0 3.5 4.5 5.0 5.0
【输出样例2】
1.0 5.0 5.5 6.5 7.5 8.0 8.0 7.0 7.5 6.5 7.5 8.0
【数据范围】
这道题不是很难,首先我们知道每个儿子的深度是不变的,而且每个点的开始时间只和他的爸爸和他爸爸的儿子有关,于是我们就往这方面去想.
我们考虑一对父子关系,对于爸爸的每一个儿子,有1/2的几率在当前儿子之前被走到,所以我们可以得出:
ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0;(爸爸的期望+1加上爸爸的所有儿子除了该点和他的子树除以2)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
il int gi()
{
int x=0,y=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
y=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*y;
}
int head[1000045],cnt;
struct edge
{
int next,to;
}e[1000045];
il void add(int from,int to)
{
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
bool vis[100045];
int size[100045];
db ans[100045];
void dfs1(int x)
{
size[x]=1;
int r=head[x];
while(r!=-1)
{
int now=e[r].to;
if(!vis[now])
{
vis[now]=1;
dfs1(now);
size[x]+=size[now];
}
r=e[r].next;
}
}
void dfs2(int x)
{
int r=head[x];
while(r!=-1)
{
int now=e[r].to;
if(!vis[now])
{
vis[now]=1;
ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0;
dfs2(now);
}
r=e[r].next;
}
}
int main()
{
memset(head,-1,sizeof(head));
int n=gi();
int x;
for(int i=2;i<=n;i++)
{
x=gi();
add(x,i);
}
vis[1]=1;
dfs1(1);
memset(vis,0,sizeof(vis));
vis[1]=1;
ans[1]=1.0;
dfs2(1);
for(int i=1;i<=n;i++)
printf("%.1f ",ans[i]);
return 0;
}