码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3534 重建

时间:2016-05-27 20:15:07      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:

题目链接: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 重建

标签:

原文地址:http://www.cnblogs.com/qzqzgfy/p/5535807.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!