题目链接:http://codeforces.com/problemset/problem/280/C
题意:给一颗n个点有根的树,每次任意删一个点,并删掉其子树,问删完整颗树的删点次数的数学期望。
题解:暴力显然太慢,考虑每个点对答案的贡献(每个点被删除次数的数学期望),根的贡献显然为1。其余点若是有父节点被删那么本身那个点则不需要被删,此时删其任意父节点和删本身概率相同,故贡献为 1/k ,k为深度(父节点数加1)。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <functional>
#include <map>
#include <bitset>
#define INF 0x7fffffff
#define REP(i,j,k) for(int i = j;i <= k;i++)
#define squr(x) (x) * (x)
#define lowbit(x) (x&(-x))
#define getint(x) scanf("%d", &(x))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
int n, m;
int a, b;
int deep[MAXN];
vector<int>edge[MAXN];
double ans;
void dfs (int x) {
ans += 1.0 / deep[x];
for(auto it:edge[x]) {
if (deep[it] == 0) {
deep[it] = deep[x] + 1;
dfs(it);
}
}
}
int main(int argc, const char * argv[]) {
getint(n);
REP(i, 1, n - 1) {
getint(a);
getint(b);
edge[a].push_back(b);
edge[b].push_back(a);
}
deep[1] = 1;
dfs(1);
printf("%.10f\n", ans);
return 0;
}