3534: [Sdoi2014]重建
变元矩阵树定理
邻接矩阵中是可以带权的,
w
i
j
wij
wij表示
i
,
j
i,j
i,j的边权,
e
i
ei
ei表示边。
定义
G
(
i
,
j
)
=
G
(
j
,
i
)
=
w
i
j
G(i,j)=G(j,i)=wij
G(i,j)=G(j,i)=wij,令
G
(
i
,
i
)
=
−
∑
j
≠
i
G
(
i
,
j
)
G(i,i)=−∑_{j≠i}G(i,j)
G(i,i)=−∑j=iG(i,j)
那么 n − 1 n−1 n−1阶主子式的值为 ∑ T ⊆ T r e e ∏ e ∈ T w e \large \sum \limits_{T\subseteq Tree}\prod \limits_{e\in T}w_e T⊆Tree∑e∈T∏we
考虑题目中的概率,我们知道最后答案是 ∑ T ⊆ T r e e ∏ e ∈ T P e ∏ e ∉ T 1 − P e \large \sum \limits_{T \subseteq Tree} \prod \limits_{e\in T} P_e \prod \limits_{e \notin T}1-P_e T⊆Tree∑e∈T∏Pee∈/T∏1−Pe
但是我们之间将边权设为 P ( i , j ) P(i,j) P(i,j)的话,最后答案就变成了 ∑ T ⊆ T r e e ∏ e ∈ T 1 − P e \large \sum \limits_{T\subseteq Tree}\prod \limits_{e\in T}1-P_e T⊆Tree∑e∈T∏1−Pe
所以我们考虑变一下这个式子,令 w i , j w_{i,j} wi,j为 P ( i , j ) 1 − P ( i , j ) \large \frac{P(i,j)}{1-P(i,j)} 1−P(i,j)P(i,j)
式子就变成了 ∑ T ⊆ T r e e ∏ e ∈ T P e 1 − P e \large \sum \limits_{T\subseteq Tree}\prod \limits_{e\in T}\frac{P_e}{1-P_e} T⊆Tree∑e∈T∏1−PePe
然后将式子都乘上一个 ∏ e ( 1 − P e ) \prod \limits_{e} (1-P_e) e∏(1−Pe)
就会发现式子变成了这样 ∑ T ⊆ T r e e ∏ e ∈ T P e ∏ e ∉ T 1 − P e \large \sum_{T \subseteq Tree} \prod \limits_{e\in T} P_e \prod \limits_{e \notin T}1-P_e ∑T⊆Treee∈T∏Pee∈/T∏1−Pe
不就是我们要求的吗。
#include<cstdio>
#include<algorithm>
#define EXP 1e-8
using namespace std;
int n;double Tmp,f[55][55];
double _abs(double x){return x<0?-x:x;}
double Gauss(){
double Mul=1.0;
for(int i=1;i<n;i++){
int k=i;
for(int j=i+1;j<n;j++) if(_abs(f[i][i])<_abs(f[j][i])) k=j;
swap(f[i],f[k]);
if(_abs(f[i][i])<EXP) return 0;
for(int j=i+1;j<n;j++){
double t=f[j][i]/f[i][i];
for(k=i;k<n;k++) f[j][k]-=t*f[i][k];
}
Mul*=f[i][i];
}
return _abs(Mul);
}
int main(){
scanf("%d",&n);Tmp=1.0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
scanf("%lf",&f[i][j]);
if(i!=j){
if(f[i][j]<EXP) f[i][j]=EXP;//防止出现0
if(f[i][j]>(1.0-EXP)) f[i][j]-=EXP;
if(i<j)Tmp*=1.0-f[i][j];f[i][j]/=1.0-f[i][j];
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(j^i) f[i][i]-=f[i][j];
printf("%.10lf\n",Gauss()*Tmp);
return 0;
}