bzoj3534 [Sdoi2014]重建

变形的$Martix-Tree$定理

发现我们要求的是$prod_{i in E}{p_{i}} * prod_{i otin E}{(1-p_{i})}$

然后呢? 矩阵树对重边也有效对吧。考虑带权图,发现建出来的矩阵的任何一个$n-1$阶主子式的行列式的值都是其所有生成树的边权之积的和

那么就可以搞了,考虑每一条边权为$frac{p_{i}}{(1-p_{i})}$,最后再乘一个$prod{(1-p_{i})}$即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define eps 1e-10
 7 #define N 55
 8 using namespace std;
 9 int n;
10 double g[N][N],a[N][N],ans=1,tmp=1;
11 void gauss(){
12     n--;
13     for(int k=1;k<=n;k++){
14         int bst=k;
15         for(int i=k+1;i<=n;i++)
16             if(fabs(a[i][k])>fabs(a[bst][k]))bst=i;
17         if(bst!=k){
18             for(int i=k;i<=n;i++)
19                 swap(a[k][i],a[bst][i]);
20             ans*=-1;
21         }
22         for(int i=k+1;i<=n;i++){
23             double t=a[i][k]/a[k][k];
24             for(int j=k;j<=n;j++)
25                 a[i][j]-=t*a[k][j];
26         }
27         ans*=a[k][k];
28     }
29 }
30 int main(){
31     scanf("%d",&n);
32     for(int i=1;i<=n;i++)
33         for(int j=1;j<=n;j++)
34             scanf("%lf",&g[i][j]);
35     for(int i=1;i<=n;i++){
36         for(int j=i+1;j<=n;j++){
37             if(g[i][j]==1)g[i][j]-=eps;
38             tmp*=(1-g[i][j]);
39             g[i][j]=g[i][j]/(1-g[i][j]);
40             a[i][i]+=g[i][j];a[j][j]+=g[i][j];
41             a[i][j]=-g[i][j];a[j][i]=-g[i][j];
42         }
43     }
44     gauss();
45     printf("%0.10lf
",ans*tmp);
46     return 0;
47 }
View Code
原文地址:https://www.cnblogs.com/Ren-Ivan/p/8185639.html