#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
using namespace std;
const int N=500010;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
int n,head[N],cnt=-1;
struct Edge{
int to,nxt;double w;
}edge[N<<1];
void add_edge(int u,int v,double w){
edge[++cnt]=(Edge){v,head[u],w};head[u]=cnt;
edge[++cnt]=(Edge){u,head[v],w};head[v]=cnt;
}
double f1[N],f2[N],q[N];
//f1 其子树令其亮
//f2 整棵树令其亮
void dfs1(int u,int f){
f1[u]=q[u];
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].to;
if(v==f) continue;
dfs1(v,u);
double tmp=edge[i].w*f1[v];
f1[u]=(f1[u]+tmp-f1[u]*tmp);
//P(A+B)=P(A)+P(B)-P(AB)
}
}
void dfs2(int u,int f,double w){
if(fabs(1.0-f1[u]*w)>=1e-6){
double t1=(f2[f]-f1[u]*w)/(1.0-f1[u]*w);
f2[u]=(f1[u]+t1*w-f1[u]*t1*w);
}
else f2[u]=f1[u];
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].to;
if(v==f) continue;
dfs2(v,u,edge[i].w);
}
}
int main(){
memset(head,-1,sizeof(head));
n=read();
int t1,t2,t3;
for(int i=1;i<n;i++){
t1=read();t2=read();t3=read();
add_edge(t1,t2,(double)t3*0.01);
}
for(int i=1;i<=n;i++)
q[i]=(double)read()*0.01;
dfs1(1,0);
dfs2(1,0,0);
double ans=0;
for(int i=1;i<=n;i++) ans+=f2[i];
printf("%.6lf\n",ans);
}
【BZOJ3566】【SHOI2014】概率充电器(概率与期望DP)
最新推荐文章于 2022-02-10 16:17:46 发布