bzoj3566 [SHOI2014]概率充电器
Description
著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:
“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!”
SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件。进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定。
随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电。
作为 SHOI 公司的忠实客户,你无法抑制自己购买 SHOI 产品的冲动。在排了一个星期的长队之后终于入手了最新型号的 SHOI 概率充电器。
你迫不及待地将 SHOI 概率充电器插入电源——这时你突然想知道,进入充电状态的元件个数的期望是多少呢?
Input
第一行一个整数:n。概率充电器的充电元件个数。充电元件由 1-n 编号。
之后的 n-1 行每行三个整数 a, b, p,描述了一根导线连接了编号为 a 和 b 的充电元件,通电概率为 p%。
第 n+2 行 n 个整数:qi。表示 i 号元件直接充电的概率为 qi%。
Output
输出一行一个实数,为进入充电状态的元件个数的期望,四舍五入到六位小数
Sample Input
1 2 50
1 3 50
50 0 0
Sample Output
HINT
对于 100%的数据,n≤500000,0≤p,qi≤100。
正解:树形$DP$+概率$DP$。
我觉得我的概率已经没救了。。
因为每个点连通也就是权值为$1$,所以这道题概率与期望的值是相等的。
因为直接计算一个点连通的概率很不方便,所以我们考虑一个点不连通的概率,于是设$f[x]$表示$x$这个点不连通的概率。
先考虑$x$的儿子对它的贡献,那么$f[x]=(1-p[x])*\prod(1-(1-f[v])*w)$,其中$v$为$x$的儿子,$w$为边连通的概率。
现在考虑$v$的父亲$x$对$v$的贡献,我们设$res$为$x$除去$v$这个点连通的概率,那么$res=1-f[x]/(1-(1-f[v])*w)$。于是$f[v]*=1-res*w$。
两个式子,我们进行两遍$dfs$,即可算出$f[x]$。那么$Ans=\sum_{i=1}^{n}1-f[i]$,于是我们成功地解决了这题。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define eps (1e-9) 16 #define N (500010) 17 #define il inline 18 #define RG register 19 #define ll long long 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 21 22 using namespace std; 23 24 struct edge{ int nt,to; long double dis; }g[2*N]; 25 26 long double f[N],p[N],ans; 27 int head[N],n,num; 28 29 il int gi(){ 30 RG int x=0,q=1; RG char ch=getchar(); 31 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 32 if (ch=='-') q=-1,ch=getchar(); 33 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 34 return q*x; 35 } 36 37 il void insert(RG int from,RG int to,RG long double dis){ 38 g[++num]=(edge){head[from],to,dis},head[from]=num; return; 39 } 40 41 il void dfs1(RG int x,RG int fa){ 42 RG int v; f[x]=1-p[x]; 43 for (RG int i=head[x];i;i=g[i].nt){ 44 v=g[i].to; if (v==fa) continue; 45 dfs1(v,x),f[x]*=1-(1-f[v])*g[i].dis; 46 } 47 return; 48 } 49 50 il void dfs2(RG int x,RG int fa){ 51 RG int v; RG long double res; 52 for (RG int i=head[x];i;i=g[i].nt){ 53 v=g[i].to; if (v==fa) continue; 54 res=1-f[x]/(1-(1-f[v])*g[i].dis); 55 if (res>eps && f[v]>eps) f[v]*=1-res*g[i].dis; 56 dfs2(v,x); 57 } 58 return; 59 } 60 61 il void work(){ 62 n=gi(); RG int u,v,w; RG long double z; 63 for (RG int i=1;i<n;++i){ 64 u=gi(),v=gi(),w=gi(),z=1.0*w/100; 65 insert(u,v,z),insert(v,u,z); 66 } 67 for (RG int i=1;i<=n;++i) w=gi(),p[i]=1.0*w/100; 68 dfs1(1,0),dfs2(1,0); for (RG int i=1;i<=n;++i) ans+=1-f[i]; 69 printf("%0.6Lf\n",ans); return; 70 } 71 72 int main(){ 73 File("3566"); 74 work(); 75 return 0; 76 }