BZOJ 3534 重建

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3534

题意:给定一个无向图,每条边有选择概率P;求选出的边恰是一棵生成树的概率。

思路:

BZOJ 3534 重建

BZOJ 3534 重建

令$G(i,j)=\frac{P(i,j)}{1-P(i,j)},tmp=\prod_{i<j} (1-P(i,j))$。那么求G的n-1阶主子式的行列式乘以tmp即可。因为在生成树中的边(u,v)是P(u,v)/(1-P(u,v)),而tmp中有(1-P(u,v))这一项,乘完之后是P(u,v),不在生成树中的边(u1,v1)也不在ans中,乘以tmp中包含的1-P(u1,v1)。这样就正好满足了条件。

const int N=55;

const double inf=1e10;
double a[N][N];
int n;

double Gauss()
{
    n--;
    double ans=1;
    int i,j,k;
    for(i=1;i<=n;i++)
    {
        k=i;
        for(j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[k][i])) k=j;
        if(k!=i)
        {
            for(j=1;j<=n;j++) swap(a[k][j],a[i][j]);
        }
        for(j=i+1;j<=n;j++)
        {
            double tmp=a[j][i]/a[i][i];
            for(k=1;k<=n;k++) a[j][k]-=a[i][k]*tmp;
        }
        if(fabs(a[i][i])<EPS) return 0;

        ans*=a[i][i];
    }

    return fabs(ans);
}

int main()
{

    n=getInt();
    int i,j;
    double tmp=1;
    for(i=1;i<=n;i++) for(j=1;j<=n;j++)
    {
        scanf("%lf",&a[i][j]);
        if(i==j) continue;
        if(a[i][j]>1-EPS) a[i][j]-=EPS;
        if(i>j) tmp*=1-a[i][j];
        a[i][j]/=1-a[i][j];
    }
    for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j) a[i][i]-=a[i][j];
    double ans=Gauss()*tmp;

    printf("%.10lf\n",ans);
}
上一篇:模拟position:fixed效果


下一篇:PHP-POSIX正则表达式函数