codeforces 696B 树形dp+概率

题意:访问一颗树,在节点上记录访问时间,每次对儿子节点的访问是随机的,问每个节点被访问时间的期望


在每个子树中,可以发现每个节点cur ,dp[cur]=dp[fa]+f(cur);
f这个函数可以发现是把fa当根节点,得到的每个子节点的期望值,这个值跟这棵子树的节点数有关,答案是(num[fa]-num[cur]-1)/2+1

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define maxn 100009

using namespace std;

int father[maxn], head[maxn], next[6 * maxn], to[6 * maxn], n, tot[maxn], Tot = 1;
double ans[maxn];

void add (int u, int v)
{
	to[++Tot] = v;
	next[Tot] = head[u];
	head[u] = Tot;
}

void dfs (int x, int fa)
{
	father[x] = fa;
	tot[x] = 1;
	for (int i = head[x];i; i = next[i])
		if (to[i] != fa)
			dfs (to[i], x), tot[x] += tot[to[i]];
}

void calc (int x, int fa)
{
	for (int i = head[x]; i; i = next[i])
		if (to[i] != fa)
		{
			double cnt = (tot[x] - 1 - tot[to[i]]) / 2.0 + 1.0;
			ans[to[i]] = cnt + ans[x];
			calc (to[i], x);
		}
}

int main ()
{
	cin >> n;
	int ta;
	rep (i, 1, n - 1)
		scanf ("%d", &ta), add (ta, i + 1), add (i + 1, ta);
	memset (tot, 0, sizeof (tot));
	dfs (1, -1);
	ans[1] = 1.0;
	calc (1, -1);
	rep (i, 1, n - 1)
		printf ("%.8f ", ans[i]);
	printf ("%.8f\n", ans[n]);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值