Bzoj3566: [SHOI2014]概率充电器

题面

传送门

Sol

算出每个点从子树内使它没电的概率和子树外使它没电的概率即可

注意算子树外使它没电的概率时,父亲转移来要除掉它的贡献,直接除可能有\(0\)的情况
可以把每个点的儿子排成一列,求一遍前后缀的积来计算

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(5e5 + 5);

IL int Input(){
	RG int x = 0, z = 1; RG char c = getchar();
	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
	return x * z;
}

double ans, f[_], g[_], tmp[_], tp[_], h[_], p[_];
int n, cnt, first[_], son[_], len;
struct Edge{
	int to, next;
	double p;
} edge[_ << 1];

IL void Add(RG int u, RG int v, RG double pi){
	edge[cnt] = (Edge){v, first[u], pi}, first[u] = cnt++;
	edge[cnt] = (Edge){u, first[v], pi}, first[v] = cnt++;
}

IL void Dfs1(RG int u, RG int ff){
	for(RG int e = first[u]; e != -1; e = edge[e].next){
		RG int v = edge[e].to;
		if(v == ff) continue;
		Dfs1(v, u);
		tp[v] = edge[e].p;
		h[v] = f[v] + (1.0 - f[v]) * (1.0 - tp[v]);
		f[u] *= h[v];
	}
}

IL void Dfs2(RG int u, RG int ff){
	len = 0;
	for(RG int e = first[u]; e != -1; e = edge[e].next)
		if(edge[e].to != ff) son[++len] = edge[e].to;
	RG double t = 1.0, ft = g[u] * (1.0 - p[u]); tmp[len + 1] = 1.0;
	for(RG int i = len; i; --i) tmp[i] = tmp[i + 1] * h[son[i]];
	for(RG int i = 1; i <= len; ++i){
		RG double pi = t * ft * tmp[i + 1];
		g[son[i]] = pi + (1.0 - pi) * (1.0 - tp[son[i]]);
		t *= h[son[i]];
	}
	for(RG int e = first[u]; e != -1; e = edge[e].next)
		if(edge[e].to != ff) Dfs2(edge[e].to, u);
}

int main(RG int argc, RG char *argv[]){
	Fill(first, -1);
	n = Input();
	for(RG int i = 1; i < n; ++i){
		RG int u = Input(), v = Input(), pi = Input();
		Add(u, v, 0.01 * pi);
	}
	for(RG int i = 1; i <= n; ++i) p[i] = 0.01 * Input(), f[i] = 1.0 - p[i];
	Dfs1(1, 0), g[1] = 1, Dfs2(1, 0);
	for(RG int i = 1; i <= n; ++i) ans += 1.0 - f[i] * g[i];
	printf("%.6lf\n", ans);
	return 0;
}

posted @ 2018-03-27 19:43  Cyhlnj  阅读(142)  评论(0编辑  收藏  举报