首先,我们需要求的是
$$\sum\limits_{Tree} \prod\limits_{E \in Tree} E(u, v) \prod\limits_{E \notin Tree} (1 - E(u, v))$$
我们知道变元矩阵树定理 ---> 不知道请见此
我们自然希望要求和的事物只跟生成树的边有关
因此考虑把$\prod\limits_{E \notin Tree} (1 - E(u, v))$转化为$\prod\limits_{E} (1 - E(u, v)) * \frac{1}{\prod\limits_{E \in Tree} (1 - E(u, v))}$
也就是说,我们定义$e(u, v) = \frac{p(u, v)}{1 - p(u, v)}$
然后就是变元矩阵树定理的裸题了......
复杂度$O(n^3)$
#include <cstdio> #include <iostream> using namespace std; #define sid 55 #define ri register int #define le long double #define eps 1e-9 int n; le all = 1, g[sid][sid], p[sid][sid]; le abs(le a) { return (a > 0) ? a : -a; } le Guass() { for(ri i = 1; i < n; i ++) { int p = i; for(ri j = i; j < n; j ++) if(abs(g[j][i]) - abs(g[p][i]) > eps) p = j; swap(g[i], g[p]); for(ri j = i + 1; j < n; j ++) { le t = g[j][i] / g[i][i]; for(ri k = i; k < n; k ++) g[j][k] -= g[i][k] * t; } } le ret = 1; for(ri i = 1; i < n; i ++) ret *= g[i][i]; return ret; } int main() { cin >> n; for(ri i = 1; i <= n; i ++) for(ri j = 1; j <= n; j ++) cin >> p[i][j]; for(ri i = 1; i <= n; i ++) for(ri j = 1; j <= n; j ++) { if(i == j) continue; if(p[i][j] > 1 - eps) p[i][j] = p[i][j] - eps; if(i < j) all *= (1 - p[i][j]); g[i][j] = p[i][j] / (1 - p[i][j]); } for(ri i = 1; i <= n; i ++) for(ri j = 1; j <= n; j ++) if(i != j) { g[i][i] += g[i][j]; g[i][j] = -g[i][j]; } printf("%.8Lf\n", Guass() * all); return 0; }