Description
Bob和Alice出去度蜜月,但Alice不慎走失,Bob在伤心过后,决定前去寻找Alice。
他们度蜜月的地方是一棵树,共有N个节点,Bob会使用下列DFS算法对该树进行遍历。
starting_time是一个容量为n的数组
current_time = 0
dfs(v):
current_time = current_time + 1
starting_time[v] = current_time
将children[v]的顺序随机排列 (每个排列的概率相同)
// children[v]v的直接儿子组成的数组
for u in children[v]:
dfs(u)
1是这棵树的根,Bob会从1出发,即运行dfs(1),现在他想知道每个点starting_time的期望值。
Solution
看到这题时我一脸懵逼。
于是我盯着样例,于是随便打打就水过去了。
这题我们设
Fi
表示
i
点的期望值,显然,
首先,我们可以先走一些子树,然后我们把全排列弄出来,(后面与题解相同),发现
j
出现在
于是从根节点往下,
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 100001
using namespace std;
int sz[N];
int to[N],next[N],last[N],num=0;
void link(int x,int y)
{
num++;
to[num]=y;
next[num]=last[x];
last[x]=num;
}
double f[N];
void find(int x)
{
sz[x]=1;
for(int i=last[x];i;i=next[i])
{
int v=to[i];
find(v);
sz[x]+=sz[v];
}
}
void dfs(int x)
{
for(int i=last[x];i;i=next[i])
{
int v=to[i];
f[v]=f[x]+(sz[x]-sz[v]-1)*0.5+1;
dfs(v);
}
}
int main()
{
int n;
cin>>n;
fo(i,2,n)
{
int x;
scanf("%d",&x);
link(x,i);
}
find(1);
f[1]=1;
dfs(1);
fo(i,1,n) printf("%.1lf ",f[i]);
}