题目链接: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);
}