感觉对期望也一无所知……(;′⌒`)╮(╯﹏╰)╭
一直在考虑怎么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\n", ans); return 0; }
原文地址:https://www.cnblogs.com/twilight-sx/p/9822964.html
时间: 2024-10-31 12:35:06