CF697D 树形DP

来源:互联网 发布:golang flag 用法 编辑:程序博客网 时间:2024/06/16 13:05

题目链接:http://codeforces.com/contest/697/problem/D

给出一颗树的描述,从根节点开始,以DFS序遍历。每次随机走向当前节点的儿子节点,没有子节点的时候就回溯。问遍历到树中每个点的期望步数。


考虑某一层DFS,假设我们已经求出该层根节点Root的答案ans[Root]。求该层x节点的答案。对于其他的节点有1/2的概率会排在该节点前面,对ans[x]的贡献就为该节点u的子树大小的1/2。那么ans[x] = ans[Root] + (size[Root]-size[x]-1]/2 + 1。

即 ans[x] = ans[Root] + (size[Root]-size[x])/2 + 1/2。


#include<bits/stdc++.h>using namespace std;const int maxn = 1e5+10;int head[maxn], tot;int sz[maxn];struct Edge{    int to, nx;    Edge(){}    Edge(int t){        to = t;    }}e[2*maxn+1];double dp[maxn];int dfs(int u, int pre){    sz[u] = 1;    for (int k = head[u]; k != -1; k = e[k].nx){        int to = e[k].to;        if (to == pre) continue;        sz[u] += dfs(to, u);    }    return sz[u];}void getans(int u, int pre){    for (int k = head[u]; k != -1; k = e[k].nx){        int to = e[k].to;        if (to == pre) continue;        dp[to] = dp[u] + 0.5 + (sz[u]-sz[to])*(1.0/2);        getans(to, u);    }}void addEdge(int from, int to){    e[++tot] = Edge(to);    e[tot].nx = head[from];    head[from] = tot;}int main(){    memset(head, -1, sizeof(head));    tot = 0;    int n;    cin >> n;    for (int i = 2; i <= n; i++){        int to;        cin >> to;        addEdge(i, to); addEdge(to, i);    }    dfs(1, 1);    dp[1] = 1.0;    getans(1, 1);    for (int i = 1; i <= n; i++)        printf("%.1f", dp[i]), printf((i==n ? "\n" : " "));    return 0;}


原创粉丝点击