题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3534
题意:给定一个无向图,每条边有选择概率P;求选出的边恰是一棵生成树的概率。
思路:
令$G(i,j)=\frac{P(i,j)}{1-P(i,j)},tmp=\prod_{i<j} (1-P(i,j))$。那么求G的n-1阶主子式的行列式乘以tmp即可。因为在生成树中的边(u,v)是P(u,v)/(1-P(u,v)),而tmp中有(1-P(u,v))这一项,乘完之后是P(u,v),不在生成树中的边(u1,v1)也不在ans中,乘以tmp中包含的1-P(u1,v1)。这样就正好满足了条件。
const int N=55; const double inf=1e10; double a[N][N]; int n; double Gauss() { n--; double ans=1; int i,j,k; for(i=1;i<=n;i++) { k=i; for(j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[k][i])) k=j; if(k!=i) { for(j=1;j<=n;j++) swap(a[k][j],a[i][j]); } for(j=i+1;j<=n;j++) { double tmp=a[j][i]/a[i][i]; for(k=1;k<=n;k++) a[j][k]-=a[i][k]*tmp; } if(fabs(a[i][i])<EPS) return 0; ans*=a[i][i]; } return fabs(ans); } int main() { n=getInt(); int i,j; double tmp=1; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%lf",&a[i][j]); if(i==j) continue; if(a[i][j]>1-EPS) a[i][j]-=EPS; if(i>j) tmp*=1-a[i][j]; a[i][j]/=1-a[i][j]; } for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j) a[i][i]-=a[i][j]; double ans=Gauss()*tmp; printf("%.10lf\n",ans); }