洛谷P3317,[SDOI2014]重建,概率期望+Matrix-Tree

正题

      其实我们之前用图造树,求的都是

                                                                                             \sum_T \prod_{e\in T}p_e.

      但是这题要我们求的是这个

                                                                                   \sum_T \prod_{e\in T}p_e*\prod_{e\not\in T}(1-p_e)

       我们发现少了什么。。。

       但是少了的东西可以被表示为

                                                                              \prod_{e\not\in T} (1-p_e)=\frac{\prod_e(1-p_e)}{\prod_{e\in T}(1-p_e)}

       所以,我们把这个东西带进原来的式子,就可以发现。

                                                                            ans=\sum_T \prod_{e\in T}p_e*\frac{\prod_e(1-p_e)}{\prod_{e\in T}(1-p_e)}

      化简就可以得到

                                                                                ans=\sum_T\prod_{e\in T}\frac{p_e}{1-p_e}*\prod_e(1-p_e)

      又因为后面东西可以直接得到,所以,将原来的边权p_e变为\frac{p_e}{1-p_e}跑行列式即可。

      下面有几个小问题需要注意。

      1.当p_e为1时,我们需要给他减去一个极小的数,来保证不会除0.

      2.我们求行列式的打法也需要改一改,变为先求出最大那一行,然后再不断与其他行相减,否则会有精度误差。

      3.通常我们认为与0误差小于1e-8的数就是0, 接近1同理。

      注意精度,否则你会被卡得很惨!!

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

int n;
const double eps=1e-8;
double d[55][55];
double last=1;
double temp=0;

double myabs(double x){
	if(x<0) return -x;
	return x;
}

double get_ans(int n){
	double ans=1;
	for(int j=1;j<=n;j++){
		int mmax=j;
		for(int i=j+1;i<=n;i++)
			if(myabs(d[i][j])>myabs(d[mmax][j])) mmax=i;
		if(mmax!=j) for(int i=1;i<=n;i++) swap(d[mmax][i],d[j][i]);
		for(int i=j+1;i<=n;i++){
			temp=d[i][j]/d[j][j];
			for(int k=j;k<=n;k++)
				d[i][k]=(d[i][k]-temp*d[j][k]);
		}
		ans*=d[j][j];
	}
	return myabs(ans);
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			scanf("%lf",&d[i][j]);
			if(i==j) continue;
			if(d[i][j]>1-eps) d[i][j]-=eps;
			if(i<j) last*=(1-d[i][j]);
			d[i][j]/=(1-d[i][j]);
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(i!=j) d[i][i]+=d[i][j],d[i][j]=-d[i][j];
	printf("%.10lf",last*get_ans(n-1));
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/81669238
今日推荐