我们算每个点能被充上电的概率, 最后加起来就是期望, 但如果直接算的话不是很好算
我们考虑先算每个点不被冲上点的概率, 那么就把从父亲不能充上电, 从儿子不能充上电, 自己本身不充上电的概率乘起来
f[i] 表示从son不能充上电, 且自己本身就充不上点的概率
g[i] 表示从父亲不能充上电的概率
h[i] 表示不能给父亲充电的概率
g[i] 有些麻烦, 我们先算父亲充不上点的概率
父亲充电可以从它的父亲, 或它当前儿子的兄弟
最后答案就是
#include<bits/stdc++.h>
#define N 1000050
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1;}
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
int first[N], nxt[N], to[N], tot; double w[N];
void add(int x, int y, double z){
nxt[++tot] = first[x], first[x] = tot;
to[tot] = y, w[tot] = z;
}
int n; double a[N];
double f[N], g[N], h[N], ans;
void dfs1(int u, int fa){
f[u] = 1 - a[u];
for(int i=first[u];i;i=nxt[i]){
int t = to[i]; if(t == fa) continue;
dfs1(t, u);
h[t] = f[t] + (1 - f[t]) * (1 - w[i]);
f[u] *= h[t];
}
}
void dfs2(int u, int fa){
for(int i=first[u];i;i=nxt[i]){
int t = to[i]; if(t == fa) continue;
double tmp = g[u] * f[u] / h[t];
g[t] = tmp + (1 - tmp) * (1 - w[i]);
dfs2(t, u);
} ans += 1 - f[u] * g[u];
}
int main(){
n = read();
for(int i=1; i<n; i++){
int x = read(), y = read(); double z = read();
add(x, y, z / 100); add(y, x, z / 100);
}
for(int i=1; i<=n; i++) a[i] = read(), a[i] /= 100;
g[1] = 1; dfs1(1, 0); dfs2(1, 0);
printf("%.6lf", ans); return 0;
}