P3317 [SDOI2014]重建

【题意】

n个城市,边被全部摧毁,给定修复每条边的概率,求修复成一棵树的期望

【分析】

具体的讲解看这里

就是一个裸的带权矩阵树定理

【代码】

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define lson now<<1
#define rson now<<1|1
typedef long long ll;
const double eps=1e-9;
double f[52][52];
double ans=1.0;
int n;
void calc()
{
    for(int i=1;i<n;i++)
    {
        int mx=i;
        for(int j=i+1;j<n;j++)
            if(fabs(f[j][i])>fabs(f[mx][i])) mx=j;
        if(mx!=i)
            for(int j=1;j<n;j++) swap(f[i][j],f[mx][j]);
        for(int k=i+1;k<n;k++)
        {
            double bl=f[k][i]/f[i][i];
            for(int j=i;j<n;j++)
                f[k][j]-=f[i][j]*bl;
        }
        if(fabs(f[i][i])<eps)
        {
            ans=0;
            return;
        }
    }
    for(int i=1;i<n;i++) ans*=f[i][i];
    ans=fabs(ans);
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%lf",&f[i][j]);
    double tmp=1.0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(fabs(f[i][j])<eps) f[i][j]=eps;
            if(fabs(1.0-f[i][j])<eps) f[i][j]=1.0-eps;
            if(i<j) tmp*=1.0-f[i][j];
            f[i][j]=f[i][j]/(1.0-f[i][j]);
        }
    for(int i=1;i<=n;i++)
    {
        f[i][i]=0;
        for(int j=1;j<=n;j++)
            if(i!=j)
                f[i][i]-=f[i][j];
    }
    calc();
    printf("%.10lf",ans*tmp);
    return 0;
}

 

posted @ 2021-05-27 11:07  andyc_03  阅读(45)  评论(0编辑  收藏  举报