Luogu

分析

显然答案为
$$
\sum_{T}\prod\limits_{e\in T}p_e\prod\limits_{e\not\in T}(1-p_e)
$$
考虑到
$$
\prod_{e\not\in T}(1-p_e)=\frac{\prod_e(1-p_e)}{\prod_{e\in T}(1-p_e)}
$$
代回去得到答案为
$$
\prod\limits_{e}(1-p_e)\sum\limits_{T}\prod\limits_{e\in T}\frac{p_e}{1-p_e}
$$
我们知道矩阵树定理求的实际上是 $\sum_T \prod_{e \in T} w_e$,于是我们可以使用矩阵树定理算出后面东西。

但是有 $p_e = 1$ 的情况,我们只需要把 $p_e$ 设为 $1-\epsilon $ 即可。

代码

//It is made by M_sea
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define re register
using namespace std;

const int N=50+10;
const double EPS=1e-8;

int n;
double G[N][N],prod=1.0;

inline double calc() {
    for (re int i=1;i<n;++i) {
        int pos=i;
        for (re int j=i+1;j<n;++j)
            if (fabs(G[j][i])>fabs(G[pos][i])) pos=j;
        swap(G[pos],G[i]);
        for (re int j=i+1;j<n;++j) {
            double t=G[j][i]/G[i][i];
            for (re int k=i;k<n;++k) G[j][k]-=t*G[i][k];
        }
    }
    double ans=1.0;
    for (re int i=1;i<n;++i) ans*=G[i][i];
    return ans;
}

int main() {
    scanf("%d",&n);
    for (re int i=1;i<=n;++i)
        for (re int j=1;j<=n;++j) {
            scanf("%lf",&G[i][j]);
            if (i==j) continue;
            if (1-G[i][j]<EPS) G[i][j]=1-EPS;
            if (i<j) prod*=(1-G[i][j]);
            G[i][j]/=(1-G[i][j]);
        }
    for (re int i=1;i<=n;++i)
        for (re int j=1;j<=n;++j)
            if (i!=j) G[i][i]+=G[i][j],G[i][j]=-G[i][j];
    printf("%.10lf\n",prod*calc());
    return 0;
}
最后修改:2021 年 03 月 23 日 05 : 06 PM