P3317 [SDOI2014]重建
【题意】
n个城市,边被全部摧毁,给定修复每条边的概率,求修复成一棵树的期望
【分析】
具体的讲解看这里
就是一个裸的带权矩阵树定理
【代码】
#include<bits/stdc++.h> using namespace std; #define mp make_pair #define fi first #define se second #define lson now<<1 #define rson now<<1|1 typedef long long ll; const double eps=1e-9; double f[52][52]; double ans=1.0; int n; void calc() { for(int i=1;i<n;i++) { int mx=i; for(int j=i+1;j<n;j++) if(fabs(f[j][i])>fabs(f[mx][i])) mx=j; if(mx!=i) for(int j=1;j<n;j++) swap(f[i][j],f[mx][j]); for(int k=i+1;k<n;k++) { double bl=f[k][i]/f[i][i]; for(int j=i;j<n;j++) f[k][j]-=f[i][j]*bl; } if(fabs(f[i][i])<eps) { ans=0; return; } } for(int i=1;i<n;i++) ans*=f[i][i]; ans=fabs(ans); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&f[i][j]); double tmp=1.0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(fabs(f[i][j])<eps) f[i][j]=eps; if(fabs(1.0-f[i][j])<eps) f[i][j]=1.0-eps; if(i<j) tmp*=1.0-f[i][j]; f[i][j]=f[i][j]/(1.0-f[i][j]); } for(int i=1;i<=n;i++) { f[i][i]=0; for(int j=1;j<=n;j++) if(i!=j) f[i][i]-=f[i][j]; } calc(); printf("%.10lf",ans*tmp); return 0; }