Codeforces 697D Puzzles

题意:有n个结点的有根树,第一个结点为根,n-1条边,第i个数表示这个数和i有一条边,求每个结点遍历的期望值,即同一层的结点的话,会先回溯到根再走到该结点

分析:树形dp,dp[i]表示第i个结点的期望值,假设第i个结点的根dp[root]已知,对于每个孩子dp[x]来说,同一层任意结点在其前面的概率都为1/2,需要先遍历它们,回溯之后再遍历当前子树,得到dp[x] = dp[root] + (size[root] - size[x] - 1) * 0.5 + 1

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct edge
{
    int to,next;
}e[maxn * 4];
int size[maxn],head[maxn];
double dp[maxn];
int t;
void add(int u,int v)
{
    e[t].to = v;
    e[t].next = head[u];
    head[u] = t++;
}
int getsize(int now,int pre)
{
    size[now] = 1;
    for(int i = head[now]; i != -1; i = e[i].next)
    {
        int v = e[i].to;
        if(v == pre)continue;
        size[now] += getsize(v,now);
    }
    return size[now];
}
void getres(int now,int pre)
{
    for(int i = head[now]; i != -1; i = e[i].next)
    {
        int v = e[i].to;
        if(v == pre)continue;
        dp[v] = dp[now] + (size[now] - size[v] - 1) * 0.5 + 1;
        getres(v,now);
    }
}
int main()
{
    int n;
    cin>>n;
    memset(head,-1,sizeof(head));
    for(int i = 2; i <= n; i++)
    {
        int x;cin>>x;
        add(x,i);
        add(i,x);
    }
    getsize(1,1);
    dp[1] = 1.0;
    getres(1,1);
    for(int i = 1; i <= n; i++)
    {
        if(i == 1)printf("%.7f",dp[i]);
        else printf(" %.7f",dp[i]);
    }
    printf("\n");
    return 0;
}


猜你喜欢

转载自blog.csdn.net/zhlbjtu2016/article/details/81047603