天天看點

【BZOJ 3534】: [Sdoi2014]重建

題目大意:(略)

題解:

  相對誤差……我好方。

  考慮答案應該為所有合法答案機率之和。對于一個合法的生成樹,其出現機率應為所有選取邊的機率出現的積 乘以 所有未選取邊不出現機率的積。

  即:

$\;\prod_{e\in tree} p_e\prod_{e\notin tree}1-p_e$

$=\prod_{e\in tree}\frac{p_e}{1-p_e}\prod_{e}1-p_e$

  然後按照新邊權列行列式即可。

代碼:

1 #include "bits/stdc++.h"
 2 
 3 using namespace std;
 4 
 5 const double eps=1e-9;
 6 
 7 const int N=100;
 8 
 9 int n;
10 double a[N][N];
11 
12  double det(){
13     double res=1;
14     for(int i=0;i<=n;++i)
15         for(int j=0;j<=n;++j)
16             if(i!=j) a[i][i]+=a[i][j],a[i][j]=-a[i][j];
17     for(int i=0;i<n;++i){
18         int p=i;
19         for(int j=i+1;j<n;++j)  if(fabs(a[j][i])>fabs(a[p][i]))p=j;
20         if(fabs(a[p][i])<eps)   return 0.0;
21         if(p!=i)  {for(int j=i;j<n;++j)    swap(a[p][j],a[i][j]);res=-res;}
22         for(int j=i+1;j<n;++j){
23             double t=a[j][i]/a[i][i];
24             for(int k=i;k<n;++k)
25                 a[j][k]-=a[i][k]*t;
26         }
27         res*=a[i][i];
28     }
29     return res;
30 }
31 
32 int main(){
33     double ans,tmp=1;
34     scanf("%d",&n);
35     for(int i=0;i<n;++i){
36         for(int j=0;j<n;++j){
37             scanf("%lf",&a[i][j]);
38             if(i==j) continue;
39             if(a[i][j]+eps>1.0) a[i][j]-=eps;
40             if(i<j) tmp*=1-a[i][j];
41             a[i][j]/=1-a[i][j];
42         }
43     }
44     --n;
45     ans=det()*tmp;
46     printf("%.10f\n",ans);
47     
48 }      

轉載于:https://www.cnblogs.com/Troywar/p/8183916.html