loading...

[CF280C]Game on Tree

链接

Description

给定有 \(n(n \le 10^5)\) 个点的树,每次操作等概率随机选取一个存在的节点删除他和他的子树,问期望的操作次数。

Solution

考虑转化题意。假设 \(c_i\) 表示某个节点被选到的次数(显然取值只有 \(0/1\)),题目相当于求 \(\sum c_i\) 的期望值。由期望的性质可得,\(E(\sum c_i) = \sum E(c_i)\)。进一步观察发现,由于 \(c_i \in \{0,1\}\),实际上 \(E(c_i)\) 等价于某个节点被选到的概率 \(p_i\)

现在只需要求 \(\sum p_i\),只要某个节点的祖先均不在其之前被选到,那这个节点就会被选到。一个节点的祖先共有 \(dep_i-1\) 个(\(dep_i\) 表示 \(1\)\(i\) 最短路径的点个数)。那么实际上我们只需要探讨操作选点序列中 \(i,fa_i, fa_{fa_i},\dots,1\) 的排列顺序,其余点不用管。一共 \(dep_i\) 个点,总共就有 \(dep_i!\) 种排列方式,其中 \(i\) 在第一位的方案总数为 \((dep_i-1)!\),所以 \(p_i=\dfrac{(dep_i-1)!}{dep_i!}=\dfrac{1}{dep_i}\)

#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, r, l) for (int i = r; i >= l; i--)
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N = 1e5+5, M = 5e5+5;
int n;
vector<int> G[N];
#define adde(u, v) G[u].push_back(v)
int dep[N];
void dfs(int x, int fa) {
	dep[x] = dep[fa]+1;
	for (auto y : G[x]) {
		if (y == fa) continue;
		dfs(y, x);
	}
}
int main() {
	FASTIO;
	cin >> n;
	rep(i, 2, n) {
		int u, v;
		cin >> u >> v;
		adde(u, v), adde(v, u);
	}
	dfs(1, 0);
	long double ans = 0;
	rep(i, 1, n) ans += 1.0/dep[i];
	cout << fixed << setprecision(20) << ans << '\n';
	return 0;
}

证明过程不会看了看题解。

posted @ 2025-02-11 18:42  goldspade  阅读(32)  评论(0)    收藏  举报