版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88189280
设(i,j)的边权为
然后使用矩阵树定理计算积和即可。
PS:
的情况可以把
设为
,实际上
就变成了eps,
就变成了极大值,因为有效位数只有一位,double是可以存1e±328的,如果概率为1的边成了环,也就没有生成树可以包括同样多的
来抵消掉极小值,舍入后也就是正确答案0。
AC Code:
#include<bits/stdc++.h>
#define maxn 55
#define eps 1e-8
using namespace std;
double P[maxn][maxn],a[maxn][maxn],sumP=1;
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>P[i][j];
P[i][j] = min(P[i][j] , 1.0-eps);
if(i!=j)
{
a[i][j] = -P[i][j] / (1-P[i][j]);
if(i<j)
sumP = sumP * (1-P[i][j]);
a[i][i] -= a[i][j];
}
}
double ans = sumP;
for(int i=2;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[j][i])
{
if(!a[i][i])
{
for(int k=i;k<=n;k++) swap(a[i][k],a[j][k]);
ans = -ans;
}
else
{
double tmp = a[j][i] / a[i][i];
for(int k=i;k<=n;k++)
a[j][k] -= a[i][k] * tmp;
}
}
for(int i=2;i<=n;i++)
ans = ans * a[i][i];
cout<<ans;
}