Puzzles CodeForces 696B 树形DP 期望计算

本文介绍了一道关于计算有根树中每个节点被访问时间期望的问题。通过递归计算每个节点的子孙数量,并利用动态规划的方法求解每个节点的时间期望。

题目https://cn.vjudge.net/problem/CodeForces-696B

题意:给出一棵n个点的有根树,节点编号从1到n,编号为1的节点为树根。
从1号节点开始dfs,从父节点访问子节点时对子节点的选择是随机的,每访问一个节点需要1秒的时间。问访问到每个节点的时间期望是多少秒。

思路:从树根向下递推。
dp(i)表示节点的时间期望,dp(fa)表示父亲节点的期望,dp(child)表示父节点对应的其中一个子节点的期望。
则dp(child)的计算可分为两种
(1)如果从父节点直接访问到子节点
dp1(child) = dp(fa) + 1
(2)若先访问其他子节点,再访问该子节点,那么先访问其他某个子节点的所需时间为访问完这个节点和它的所有子孙所需的时间。由于任意一个节点先于该子节点访问的概率都为0.5,是相等的,所以其他节点的访问时间期望贡献具有可加性,因此
dp2(child) = 0.5 * (child的兄弟节点数 + 所有兄弟节点对应所有子孙数)

综上:dp(child) = dp(fa) + 1 + 0.5 * (child的兄弟节点数 + 所有兄弟节点对应所有子孙数)

实现上先递归处理出所有节点的子孙数,然后再dfs按上式递推即可。

代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;

const int maxn = 100000 + 10;

int n;

int fa[maxn];
vector<int> child[maxn];
int childsize[maxn];
double ans[maxn];

int cntchild(int u)
{
    if (child[u].empty())
    {
        return childsize[u] = 1;
    }
    childsize[u] = 1;
    for (int i = 0; i < child[u].size(); i++)
    {
        childsize[u] += cntchild(child[u][i]);
    }
    return childsize[u];
}

void dfs(int u)
{
    for (int i = 0; i < child[u].size(); i++)
    {
        int next = child[u][i];
        ans[next] = ans[u] + 1 + 0.5 * (childsize[u] - 1 - childsize[next]);
        dfs(next);
    }
}

int main()
{
    cin >> n;
    fa[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        scanf("%d", &fa[i]);
        child[fa[i]].push_back(i);
    }
    cntchild(1);
    ans[1] = 1;
    dfs(1);
    for (int i = 1; i <= n; i++)
    {
        if (i != 1)
        {
            printf(" ");
        }
        printf("%.1f", ans[i]);
    }
    return 0;
}
### Codeforces Problem 2071D1 Description The provided references do not contain specific information about Codeforces problem 2071D1. However, based on similar problems from the platform such as those mentioned in the references, one can infer that these types of challenges typically involve algorithmic puzzles with varying levels of difficulty depending on constraints. For instance, some problems are presented in multiple versions where only the input size differs[^1]. In another case, a simple condition check like comparing characters within a string suffices for solving certain tasks[^2]. Given this pattern, it's likely that **Codeforces problem 2071D1** would follow a structure wherein: - A base challenge is introduced. - Constraints define whether the solver should approach using an optimized method suitable for larger inputs or opt for simpler logic applicable under smaller limits. Unfortunately, without direct access to the exact details of problem 2071D1, providing its precise description or solution isn't feasible here. For obtaining accurate descriptions and solutions related specifically to Codeforces contest questions including 2071D1, visiting the official website or forums dedicated to competitive programming discussions might be beneficial. ```cpp // Example C++ code snippet demonstrating how solutions may look structurally, // but note this does NOT represent the actual solution for 2071D1: #include <iostream> using namespace std; void exampleSolve() { int n; cin >> n; // Hypothetical processing... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值