God this question is so good...
Let f[i] be the probability that i is out of power, and initialize $f[i]=1-q[i]$
After that, the electricity of x has three sources:
1.x own electricity
2.x's son called it
3.x's father called it
For the 2 and 3 operations, do a tree DP respectively, the first time is to use the son to push out the father, and the second time is to use the father to push out the son.
#include<cstdio> #include<algorithm> #include<cstring> #include<cctype> #include<cstdlib> #define maxn 500050 #define eps 1e-9 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num = num * 10 + ch - 0 ' ; ch=getchar(); } return num*f; } struct Edge{ int next,to;double val; }edge[maxn*2]; int head[maxn],num; inline void add(int from,int to,double val){ edge[++num]=(Edge){head[from],to,val}; head[from]=num; } double f[maxn]; double q[maxn]; void dfs(int x,int fa){ f[x]=1-q[x]; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; dfs(to,x); f[x]*=1-(1-f[to])*edge[i].val; } return; } void dgs(int x,int fa){ for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(to==fa) continue; double ret=1-f[x]/(1-(1-f[to])*edge[i].val); if(ret>eps&&f[to]>eps) f[to]*=1-ret*edge[i].val; dgs(to,x); } return; } int main(){ int n=read(); for(int i=1;i<n;++i){ int from=read(),to=read(),p=read(); add(from,to,p*1.0/100); add(to,from,p*1.0/100); } for(int i=1;i<=n;++i) q[i]=read()*1.0/100; dfs(1,1); dgs(1,1); double ans=0; for(int i=1;i<=n;++i) ans+=1-f[i]; years += eps; printf("%.6lf",ans); return 0; }