Description:
每条边有一个存在的概率,问一棵生成树的出现概率。
Solution:
相当于生成树上存在的概率乘其他边不存在的概率。
矩阵树定理可以求出每棵生成树边权的乘积的和,那么我们把边权变成pi1−pipi1−pi,做矩阵树定理,最后乘上∏1−pi∏1−pi即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 55;
const double eps = 1e-8;
int n;
double tmp = 1.0;
double a[maxn][maxn];
double det(int n) {
for(int i = 1; i <= n; ++i) {
int p = i;
for(int j = i + 1; j <= n; ++j) {
if(fabs(a[j][i]) > fabs(a[p][i])) {
p = j;
}
}
for(int j = 1; j <= n; ++j) {
swap(a[i][j], a[p][j]);
}
if(fabs(a[i][i]) < eps) {
return 0.0;
}
for(int j = i + 1; j <= n; ++j) {
double t = a[j][i] / a[i][i];
for(int k = i; k <= n; ++k) {
a[j][k] -= t * a[i][k];
}
}
}
double ret = 1.0;
for(int i = 1; i <= n; ++i) {
ret *= a[i][i];
}
return ret;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
scanf("%lf", &a[i][j]);
if(i != j) {
if(a[i][j] > 1.0 - eps) {
a[i][j] -= eps;
}
if(i < j) {
tmp = tmp * (1.0 - a[i][j]);
}
a[i][j] /= 1.0 - a[i][j];
}
}
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j) {
if(i != j) {
a[i][i] += a[i][j];
a[i][j] = -a[i][j];
}
}
}
printf("%.10f\n", det(n - 1) * tmp);
return 0;
}

本文介绍了一种计算带概率边权图中生成树概率的方法。利用矩阵树定理将边的存在概率转换为特定形式,通过计算行列式求得生成树概率,并给出具体实现代码。

301

被折叠的 条评论
为什么被折叠?



