BZOJ 3534 重建

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

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

思路:

BZOJ 3534 重建

令G(i,j)=P(i,j)/(1-P(i,j)),tmp=∏(1-P(i,j))(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);

}

 

你可能感兴趣的:(ZOJ)