P3317 [SDOI2014]重建

本文介绍了一种利用变元矩阵树定理求解特定概率问题的方法。通过矩阵树定理,文章推导出了考虑非树边概率的生成树概率公式,并给出了相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

变元矩阵树定理:求所有生成树的总边积的和,行列式中 $A[i][i]$ 为总边权和,$A[i][j]$ 为 $i,j$ 之间边权相反数

这题显然考虑这个东西

但是不能直接把边权变成概率,还要考虑非树边出现的概率

就是说原本矩阵树可以求 $\sum _{Tree}\prod _{e\in Tree}P[e]$

但是此题要求的是 $\sum _{Tree}\prod _{e\in Tree}P[e]\prod _{e\notin Tree}(1-P[e])$

考虑化一下上面那个式子:

   $\sum _{Tree}\prod _{e\in Tree}P[e]\prod _{e\notin Tree}(1-P[e])$

$=\sum _{Tree}\prod _{e\in Tree}P[e]\frac{\prod _{e}(1-P[e])}{\prod _{e\in Tree}(1-P[e])}$

$=\prod _{e}(1-P[e])\sum _{Tree}\prod _{e\in Tree}\frac{P[e]}{(1-P[e])}$

然后就可以矩阵树了

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double db;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=107;
const db eps=1e-7;
int n;
db A[N][N],ans=1;
db Gauss()
{
    db res=1.0;
    for(int i=1;i<n;i++)
    {
        int tmp=i;
        for(int j=i+1;j<n;j++)
            if(fabs(A[tmp][i])<fabs(A[j][i])) tmp=j;
        if(tmp!=i) swap(A[tmp],A[i]),res=-res;
        for(int j=i+1;j<n;j++)
        {
            db t=A[j][i]/A[i][i];
            for(int k=i;k<n;k++) A[j][k]-=t*A[i][k];
        }
        res*=A[i][i];
    }
    return fabs(res);
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) scanf("%lf",&A[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            db t= (1.0-A[i][j])<eps ? eps : 1.0-A[i][j];//防止分母为0
            A[i][j]/=t; if(i<j) ans*=t;
        }
    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]*=-1;
    printf("%.10lf",ans*Gauss());
    return 0;
}

 

转载于:https://www.cnblogs.com/LLTYYC/p/10627813.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值