zoukankan      html  css  js  c++  java
  • bzoj 3566: [SHOI2014]概率充电器 数学期望+换根dp

    题意:给定一颗树,树上每个点通电概率为 $q[i]$%,每条边通电的概率为 $p[i]$%,求期望充入电的点的个数.

    期望在任何时候都具有线性性,所以可以分别求每个点通电的概率(这种情况下期望=概率 $ imes 1$ )然后累加.

    然而,直接求通电的概率不是很好求,所以可以求不通电的概率,然后 $1$ 减去这个就是通电的概率了~

    先假定以 $1$ 为根,令 $f[i]$ 表示仅考虑 $i$ 的子树及 $i$ 的影响时 $i$ 充不到电的概率.

    则有: $f[i]=(1-q[i])prod_{ein(u,v)}(1-p[i]+p[i]f[i])$

    而在 $i=1$ 时,$f[i]$ 就是 $1$ 号点不通电的概率,但是对于其余所有点,我们还需考虑父亲的影响:考虑换根dp

    令 $g[i]$ 表示 $i$ 点的最终答案,即考虑所有情况下 $i$ 点不通电的概率.

    那么,当 $i=1$ 时,$g[1]=f[1]$

    而 $i eq1$ 时,令 $p$ 表示只考虑父亲对 $i$ 的影响,而 $p=frac{g[fa]}{1-p[e]+p[e]f[i]}$ $e$ 为 $i$ 到 $fa$ 的边.

    则有 $g[i]=f[i] imes (1-p[e]+p[e] imes p)$

    求完之后再累加一下即可. 

    #include <bits/stdc++.h>    
    #define N 500002         
    #define LL long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int n,edges;    
    double f[N],g[N],perc[N<<1],q[N]; 
    int hd[N],to[N<<1],nex[N<<1]; 
    void add(int u,int v,double c) 
    {
    	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,perc[edges]=c; 
    } 
    void dfs1(int u,int ff)          
    {
    	f[u]=1-q[u];           
    	for(int i=hd[u];i;i=nex[i])        
    	{  
    		int v=to[i]; 
    		if(v==ff)    continue;                              
    		dfs1(v,u); 
    		f[u]*=(1-perc[i]+perc[i]*f[v]);             
    	}
    } 
    void dfs2(int u,int ff,int j) 
    {  
    	if(u==1)   g[u]=f[u];  
    	else 
    	{
    		double p=g[ff]/(1-perc[j]+perc[j]*f[u]);            
    		g[u]=f[u]*(1-perc[j]+perc[j]*p);      
    	} 
    	for(int i=hd[u];i;i=nex[i]) 
    	{
    		int v=to[i]; 
    		if(v==ff) continue;   
    		dfs2(v,u,i);   
    	}
    }
    int main() 
    { 
    	// setIO("input");  
    	int i,j; 
    	scanf("%d",&n);            
    	for(i=1;i<n;++i) 
    	{
    		int x,y,z; 
    		scanf("%d%d%d",&x,&y,&z),add(x,y,(double)z/100),add(y,x,(double)z/100);    
    	}    
    	for(i=1;i<=n;++i)    scanf("%lf",&q[i]),  q[i]/=100;     
    	dfs1(1,0); 
    	dfs2(1,0,0);    
    	double ans=0;   
    	for(i=1;i<=n;++i)  ans+=1.0-g[i]; 
    	printf("%.6lf",ans);               
    	return 0; 
    }   
    

      

  • 相关阅读:
    [常用的Cmd运行命令]
    [Ajax三级联动 无刷新]
    [占位符 &nbsp; ]
    [String.Format(转换时间格式)]
    [ASP.NET应用到的时间处理函数]
    [SQL Server常用系统存储过程大全]
    [SQL Server创建视图时的注意点]
    [SQL Server 视图的创建- (create view必须是批处理中仅有的语句问题)]
    [SQL 高级查询运算符的用法 UNION (ALL),EXCEPT(ALL),INTERSECT(ALL) ]
    layui 表单遇到的小问题
  • 原文地址:https://www.cnblogs.com/guangheli/p/11794238.html
Copyright © 2011-2022 走看看