题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3534
题意:给定一个无向图,每条边有选择概率P;求选出的边恰是一棵生成树的概率。
首先,将A[i][j]从01变成这条边的概率,然后a[i][i]减去每条有i的边的概率,对此求n-1阶主子式的行列式,
可以得到:Σ(p[i]*p[i+1]*p[i+2]*...p[n-1])(p代表某棵树的集合中,这个集合里每条边选中的概率)
可是,这个概率只与树边有关,却无法保证没有非树边
我们重新考虑,令原先加入的a[i][j]变成(a[i][j]/(1-a[i][j])),再令tmp=(1-p[1])*(1-p[2])*...(1-p[m]),然后求行列式,最后选中的树边的因子,都是P[i],不选中的非树边的因子是(1-p[i]),于是问题完美解决。
1 #include2 #include 3 #include 4 #include 5 #include 6 double a[505][505]; 7 const double eps=1e-10; 8 int n; 9 int zero(double x){10 if (x<-eps) return -1;11 else return x>eps;12 }13 double gauss(){14 double res=1;15 for (int i=1;i<=n;i++){16 int k=i;17 for (int j=i+1;j<=n;j++) if (fabs(a[j][i])>fabs(a[k][i])) k=j;18 if (k!=i){19 for (int j=1;j<=n;j++) std::swap(a[i][j],a[k][j]);20 }21 for (int j=i+1;j<=n;j++){22 double tmp=a[j][i]/a[i][i];23 for (int k=i;k<=n;k++)24 a[j][k]-=a[i][k]*tmp;25 }26 if (!zero(a[i][i])) return 0;27 }28 for (int i=1;i<=n;i++) res*=a[i][i];29 return std::fabs(res);30 }31 int main(){32 scanf("%d\n",&n);33 double tm=1;34 for (int i=1;i<=n;i++)35 for (int j=1;j<=n;j++){36 scanf("%lf",&a[i][j]);37 if (i==j) continue;38 if (a[i][j]>1-eps) a[i][j]-=eps;39 if (i