除去不选的边要为答案做出 \(1 - g\) 的贡献,这道题完全就是个矩阵-树板子了。考虑怎么化掉 \(1 - g\)。
一条边由不选转为选,其贡献由 \(1 - g\) 变为了 \(g\),所以边权为 \(\frac g {1 - g}\)。
#include <cstdio>
#include <cmath>
#include <algorithm>
const int MAXN = 59;
const double EPS = 1e-12;
double a[MAXN][MAXN], s = 1.0;
double det(int n){
double res = 1.0;
for(int i = 1; i <= n; ++i){
int r = i;
for(int j = i + 1; j <= n; ++j)
if(std::fabs(a[r][i]) < std::fabs(a[j][i]))
r = j;
if(i ^ r){
std::swap(a[i], a[r]);
res = -res;
}
if(std::fabs(a[i][i]) < EPS)
return 0;
for(int j = i + 1; j <= n; ++j){
double d = a[j][i] / a[i][i];
for(int k = i; k <= n; ++k)
a[j][k] -= a[i][k] * d;
}
res *= a[i][i];
}
return res;
}
double g[MAXN][MAXN];
int n;
inline void insert(int u, int v, double m){
a[u][u] += m, a[v][v] += m;
a[u][v] -= m, a[v][u] -= m;
}
int main(){
std::scanf("%d", &n);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
std::scanf("%lf", &g[i][j]);
for(int i = 1; i <= n; ++i)
for(int j = i + 1; j <= n; ++j)
insert(i, j, g[i][j] / (1.0 - g[i][j] + EPS)), s *= (1.0 - g[i][j] + EPS);
std::printf("%.12f\n", s * det(n - 1));
return 0;
}