bzoj 3566: [SHOI2014]概率充电器 数学期望+换根dp
作者:互联网
code:
#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; }
标签:code,3566,int,long,SHOI2014,500002,换根,define 来源: https://www.cnblogs.com/guangheli/p/11794238.html