CF1874C Jellyfish and EVA 题解
因为终点状态确定,所以考虑从终点往前 DP。
先解决一个小问题,如何求出对于每个点 $k$,出度为 $i$,选取第 $j$ 个点的概率。发现对于一个点 $k$,选取概率只与 $i$ 有关,我们先预处理。
稍加思考,当我们选择第 $j$ 个点时,Asuka 可能选择前面 $j$ 个点中的一个,也可能选后 $i - j$ 个点中的一个,所以有递推式:$$f_{i,j} = \sum_{2 \le j\le i} f_{i-2,j-1} \times \frac{i-j}{i} + f_{i-2,j-2} \times \frac{j-2}{i}$$
然后我们贪心的让 $k$ 连向的点的期望值最大点对应上 $f_{i,j}$ 中最大的值。即我们可以构造出一个选择的顺序,使得 $f_{i,k}$ 与 $dp_{s \in son_k}$ 最大值两两对应,次大值两两对应 $\cdots$。
#include<bits/stdc++.h>
using namespace std;
typedef double dl;
const int N = 5050;
const int M = 2e5 + 500;
int T, n, m;
dl as[N], f[N][N];
vector<int> E[N];
vector<dl> vc;
void solve() {
for(int i = 1; i < N; ++i) as[i] = 0, E[i].clear();
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; ++i) {
int u, v;
scanf("%d %d", &u, &v);
E[u].push_back(v);
}
as[n] = 1;
for(int i = n - 1; i; --i) {
vc.clear();
for(auto P : E[i]) vc.push_back(as[P]);
sort(vc.begin(), vc.end(), greater<dl>());
for(int j = 0; j < vc.size(); ++j) as[i] += vc[j] * f[vc.size()][j + 1];
}
printf("%.12lf\n", as[1]);
}
int main() {
for(int i = 1; i < N; ++i) {
f[i][1] = 1;
for(int j = 2; j < i; ++j) {
f[i][j] += f[i - 2][j - 1] * (i - j);
}
for(int j = 2; j <= i; ++j) {
f[i][j] += f[i - 2][j - 2] * (j - 2);
}
for(int j = 1; j < N; ++j) f[i][j] /= i;
}
scanf("%d", &T);
while(T--) solve();
return 0;
}