题解 CF1060F 【Shrinking Tree】
一个比较难以理解的dp神题。
首先我们可以考虑每次随机缩一条边等效于有一个长度为
现在我们干脆把
我们考虑这个
当合并过来一个儿子
考虑
①:
②:
那么现在我们就需要改一下
这样的话,我们重新来看一下上面两个情况:
①:显然对于一个
②:对于
那么现在我们把每个儿子的
那么我们考虑两个儿子
前面的
然后就
上代码~
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
namespace ywy {
double dp[55][55], g[55], jc[55];
inline double cnm(int n, int m) {
if (n < m)
return (0);
return ((jc[n] / jc[m]) / jc[n - m]);
}
typedef struct _b {
int dest;
int nxt;
} bian;
bian memchi[1000001];
int gn = 1, heads[55];
inline void add(int s, int t) {
memchi[gn].dest = t;
memchi[gn].nxt = heads[s];
heads[s] = gn;
gn++;
}
int size[55];
double h[55];
void dfs(int pt, int baba) {
size[pt] = 1;
dp[pt][0] = 1;
for (register int i = heads[pt]; i; i = memchi[i].nxt) {
if (memchi[i].dest == baba)
continue;
dfs(memchi[i].dest, pt);
for (register int j = 0; j <= size[memchi[i].dest]; j++) {
g[j] = 0;
for (register int k = 0; k < j; k++) g[j] += 0.5 * dp[memchi[i].dest][k];
g[j] += (size[memchi[i].dest] - j) * dp[memchi[i].dest][j];
}
for (register int j = 0; j <= size[pt] + size[memchi[i].dest]; j++) h[j] = 0;
for (register int j = 0; j < size[pt]; j++) {
for (register int k = 0; k <= size[memchi[i].dest]; k++) {
h[j + k] += dp[pt][j] * g[k] *
cnm(size[pt] - 1 - j + size[memchi[i].dest] - k, size[pt] - 1 - j) *
cnm(j + k, j);
}
}
size[pt] += size[memchi[i].dest];
for (register int j = 0; j < size[pt]; j++) dp[pt][j] = h[j];
}
}
void ywymain() {
int n;
cin >> n;
jc[0] = 1;
for (register int i = 1; i <= n; i++) jc[i] = jc[i - 1] * i;
for (register int i = 1; i < n; i++) {
int s, t;
cin >> s >> t;
add(s, t);
add(t, s);
}
for (register int i = 1; i <= n; i++) {
memset(dp, 0, sizeof(dp));
dfs(i, 0);
printf("%.10lf\n", dp[i][n - 1] / jc[n - 1]);
}
}
}
int main() {
ywy::ywymain();
return (0);
}