BZOJ 3534 重建

Posted GFY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3534 重建相关的知识,希望对你有一定的参考价值。

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

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

首先,将A[i][j]从01变成这条边的概率,然后a[i][i]减去每条有i的边的概率,对此求n-1阶主子式的行列式,

可以得到:Σ(p[i]*p[i+1]*p[i+2]*...p[n-1])(p代表某棵树的集合中,这个集合里每条边选中的概率)

可是,这个概率只与树边有关,却无法保证没有非树边

我们重新考虑,令原先加入的a[i][j]变成(a[i][j]/(1-a[i][j])),再令tmp=(1-p[1])*(1-p[2])*...(1-p[m]),然后求行列式,最后选中的树边的因子,都是P[i],不选中的非树边的因子是(1-p[i]),于是问题完美解决。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 double a[505][505];
 7 const double eps=1e-10;
 8 int n;
 9 int zero(double x){
10     if (x<-eps) return -1;
11     else return x>eps;
12 }
13 double gauss(){
14     double res=1;
15     for (int i=1;i<=n;i++){
16         int k=i;
17         for (int j=i+1;j<=n;j++) if (fabs(a[j][i])>fabs(a[k][i])) k=j;
18         if (k!=i){
19             for (int j=1;j<=n;j++) std::swap(a[i][j],a[k][j]);
20         }
21         for (int j=i+1;j<=n;j++){
22          double tmp=a[j][i]/a[i][i];
23          for (int k=i;k<=n;k++)
24           a[j][k]-=a[i][k]*tmp;
25         }
26         if (!zero(a[i][i])) return 0;
27     }
28     for (int i=1;i<=n;i++) res*=a[i][i];
29     return std::fabs(res);
30 }
31 int main(){
32     scanf("%d\n",&n);
33     double tm=1;
34     for (int i=1;i<=n;i++)
35         for (int j=1;j<=n;j++){
36             scanf("%lf",&a[i][j]);
37             if (i==j) continue;
38             if (a[i][j]>1-eps) a[i][j]-=eps;
39             if (i<j) tm*=1-a[i][j];
40             a[i][j]/=1-a[i][j];
41         }
42     for (int i=1;i<=n;i++)
43      for (int j=1;j<=n;j++)
44       if (i!=j)
45        a[i][i]-=a[i][j];
46     n--;    
47     printf("%.10lf\n",gauss()*tm);      
48 }

 

以上是关于BZOJ 3534 重建的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3534 [Sdoi2014]重建

bzoj3534 [Sdoi2014]重建

BZOJ3534 [Sdoi2014]重建 矩阵树定理

生成树

bzoj2957 楼房重建——线段树

bzoj2957楼房重建——线段树