版权声明:欢迎dalao指出错误暴踩本SD,蒟蒻写的博客转载也要吱一声 https://blog.csdn.net/enjoy_pascal/article/details/89716458
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的期望值。
analysis
-
观察样例,可知对于一个节点的任意两个儿子节点,一个在另一个前面的概率总是
-
也就是说每个节点对任意一个兄弟节点的期望步数值贡献为该节点子树大小
-
所以 ,整理得
code
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define MAXM MAXN<<1
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])
#define O3 __attribute__((optimize("-O3")))
using namespace std;
ll last[MAXM],next[MAXM],tov[MAXM],size[MAXN];
double ans[MAXN];
ll n,tot;
O3 inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
O3 inline void link(ll x,ll y)
{
next[++tot]=last[x],last[x]=tot,tov[tot]=y;
}
O3 inline void dfs(ll x)
{
size[x]=1;rep(i,x)dfs(tov[i]),size[x]+=size[tov[i]];
}
O3 inline void dfs1(ll x)
{
rep(i,x)ans[tov[i]]=ans[x]+(size[x]-size[tov[i]]+1)/2.0,dfs1(tov[i]);
}
O3 int main()
{
freopen("T1.in","r",stdin);
n=read();
fo(i,2,n){ll x=read();link(x,i);}
dfs(1),ans[1]=1.0,dfs1(1);
fo(i,1,n)printf("%.1lf ",ans[i]);
printf("\n");
return 0;
}