直接M-T肯定不对
推出的是对于所有树的生成概率的和,可以考虑行列式的期望,再交换求和号即可
同时乘上π(1-P)再变化初始的概率就有点厉害了
一种变化的技巧
代码:
#include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^'0') #define ld long double using namespace std; typedef long long ll; il void rd(int &x){ char ch;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=55; const double eps=1e-8; ld G[N][N],f[N][N]; int n; ld GUASS(int n){ for(reg i=1;i<=n;++i){ int id=0; for(reg j=i;j<=n;++j){ if(fabs(f[j][i])>fabs(f[id][i])) id=j; } if(id!=i){ for(reg j=i;j<=n;++j){ swap(f[i][j],f[id][j]); } } for(reg k=i+1;k<=n;++k){ if(fabs(f[k][i])>eps){ ld tmp=f[k][i]/f[i][i]; for(reg j=i;j<=n;++j){ f[k][j]-=f[i][j]*tmp; } } } } ld ret=1.00; for(reg i=1;i<=n;++i){ ret=ret*f[i][i]; } return ret; } int main(){ rd(n); ld tmp=1.00; for(reg i=1;i<=n;++i) { for(reg j=1;j<=n;++j){ scanf("%Lf",&G[i][j]); if(fabs(G[i][j])<eps) G[i][j]=eps; if(fabs(1-G[i][j])<eps) G[i][j]=1-eps; if(i<j) tmp=tmp*(1.00-G[i][j]); G[i][j]=G[i][j]/(1.00-G[i][j]); if(i<j) f[i][i]+=G[i][j],f[j][j]+=G[i][j]; } } for(reg i=1;i<=n;++i){ for(reg j=1;j<=n;++j){ f[i][j]-=G[i][j]; } } ld ans=GUASS(n-1); ans=ans*tmp; printf("%.10Lf",ans); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/2/22 23:02:49 */