【题解】CF#280 C-Game on Tree

  感觉对期望也一无所知……(;′⌒`)╮(╯﹏╰)╭

  一直在考虑怎么dp,最后看了题解——竟然是这样的???【震惊】但是看了题解之后,觉得确实很有道理……

  我们可以考虑最后答案的组成,可以分开计算不同的点对于答案的贡献(期望具有线性性)。我们可以把这个染色的过程看做每一个节点均需要被染色,但只有第一个被染色的节点会消耗1点代价。这样我们就可以分别分析每个点对于答案产生贡献的概率,答案即为概率之和。而一个点会对答案产生影响的概率是多少?实际上这只与它到根的链上的节点是相关的,因为只要在染色它的祖先节点之前染色它,它就会对答案产生为1的贡献。

  那么当它和它的祖先均未被染色时,显然有选择任意节点的概率相等,显然有选择它的概率为 (frac{1}{dep[u]})(如果选择了其他节点,则该节点无法再产生贡献)。于是……这题就做完了。强啊!%%%

#include <bits/stdc++.h>
using namespace std;
#define maxn 200000
#define db double
int n, dep[maxn];
db ans;

int read()
{
    int x = 0, k = 1;
    char c; c = getchar();
    while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * k;
}

struct edge
{
    int cnp, to[maxn], last[maxn], head[maxn];
    edge() { cnp = 2; }
    void add(int u, int v)
    {
        to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
        to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
    }
}E1;

void dfs(int u, int fa)
{
    for(int i = E1.head[u]; i; i = E1.last[i])
    {
        int v = E1.to[i];
        if(v == fa) continue;
        dep[v] = dep[u] + 1; dfs(v, u);
    }
}

int main()
{
    n = read();
    for(int i = 1; i < n; i ++)
    {
        int u = read(), v = read();
        E1.add(u, v);
    }
    dep[1] = 1; dfs(1, 0);
    for(int i = 1; i <= n; i ++) ans += (1.0 / (db) dep[i]);
    printf("%.10lf
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/twilight-sx/p/9822964.html