Bzojphp
洛谷code
首先考慮從兒子來的貢獻:get
$$ f[u]=\prod_{v \in son[u]}f[v]+(1-f[v])\times(1-dis[i]) $$string
根據容斥原理,就是兒子直接亮的機率減去當兒子不亮且他們之間的路徑均不直接亮時的機率it
接着考慮從父親來的貢獻,設$p$爲:$\frac{g[u]\times f[u]}{f[v]+(1-f[v])\times(1-dis[i])}$io
則:(畫畫圖就能夠理解)class
$$ g[v]=p+(1-p)\times(1-dis[i]) $$原理
最後答案就是im
$$ \sum_{i=1}^n1-f[i]\times g[i] $$sort
#include <cstdio> #include <cstring> #include <algorithm> using std::min; using std::max; using std::swap; using std::sort; typedef long long ll; typedef double db; template<typename T> void read(T &x) { int flag = 1; x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); } while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag; } const int N = 5e5 + 10; db poi[N], ret, son[N], fa[N], dis[N << 1]; int n, to[N << 1], nxt[N << 1], from[N], cnt; bool vis[N]; inline void addEdge(int u, int v, db w) { to[++cnt] = v, nxt[cnt] = from[u], dis[cnt] = w, from[u] = cnt; } void dfs1(int u) { vis[u] = 1, son[u] = 1. - poi[u]; for(int i = from[u]; i; i = nxt[i]) { int v = to[i]; if(vis[v]) continue; dfs1(v); son[u] *= son[v] + (1. - son[v]) * (1. - dis[i]); } vis[u] = 0; } void dfs2(int u) { vis[u] = 1; for(int i = from[u]; i; i = nxt[i]) { int v = to[i]; if(vis[v]) continue; db p = fa[u] * son[u] / (son[v] + (1. - son[v]) * (1. - dis[i])); fa[v] = p + (1. - p) * (1. - dis[i]); dfs2(v); } } int main () { read(n); for(int i = 1, u, v, w; i < n; ++i) read(u), read(v), read(w), addEdge(u, v, w / 100.), addEdge(v, u, w / 100.); for(int i = 1, p; i <= n; ++i) read(p), poi[i] = p / 100.; fa[1] = 1, dfs1(1), dfs2(1); for(int i = 1; i <= n; ++i) ret += 1. - fa[i] * son[i]; return printf("%.6lf\n", ret) & 0; }