1. 程式人生 > >luoguP3317 [SDOI2014]重建 變元矩陣樹定理 + 概率

luoguP3317 [SDOI2014]重建 變元矩陣樹定理 + 概率

htm ever turn name https 因此 mage for rac

技術分享圖片

首先,我們需要求的是

$$\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; }

luoguP3317 [SDOI2014]重建 變元矩陣樹定理 + 概率