CF697D 樹形DP

題目鏈接: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章