• BZOJ3566: [SHOI2014]概率充电器


    这题要算期望,个数的期望

    容易发现每一个点对期望的贡献就是它被接通的概率

    之后考虑 dp

    在玩方程的时候会发现这样一个事情:如果状态定义为被接通的概率的话,在转移时要加子树的然后再除个总概率什么的,总之很麻烦

    但是可以考虑一下计算不被接通的概率,这样计算一个 pi 就好了

    之后容易想到二次扫描换根

    转移子树的方程是 : d[x] = (1 - p[x]) * ∏[d[son[i]] * edge[i].val + 1 - edge[i].val]

    转移以当前点为根的方程是 : f[x] = d[x] * {(1 - edge[i].val) +edge[i].val * [f[fa] / (d[x] *edge[i].val + 1 - edge[i].val)]}

    需要注意的是这样定义状态会导致转移方程中出现除,并且这个除数是一个带减号的式子,所以可能会除 0,判掉就好


    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cstdio>
    using namespace std;
    
    const int MAXN = 500005;
    const double eps = 1e-6;
    
    struct EDGE{
    	int nxt, to;
    	double val;
    	EDGE(int NXT = 0, int TO = 0, double VAL = 0.0) {nxt = NXT; to = TO; val = VAL;}
    }edge[MAXN << 1];
    int n, totedge;
    int head[MAXN];
    double d[MAXN], f[MAXN], p[MAXN];
    double ans;
    
    inline void add(int x, int y, double v) {
    	edge[++totedge] = EDGE(head[x], y, v);
    	head[x] = totedge;
    	return;
    }
    void dfs(int x, int fa) {
    	d[x] = 1.0 - p[x];
    	for(int i = head[x]; i; i = edge[i].nxt) if(edge[i].to != fa) {
    		int y = edge[i].to;
    		dfs(y, x);
    		d[x] *= ((1.0 - edge[i].val) + (edge[i].val * d[y]));
    	}
    	return;
    }
    void efs(int x, int fa) {
    	for(int i = head[x]; i; i = edge[i].nxt) if(edge[i].to != fa) {
    		int y = edge[i].to;
    		double k = (d[y] * edge[i].val + 1.0 - edge[i].val);
    		if(k > eps) f[y] = d[y] * ((1.0 - edge[i].val) + edge[i].val * f[x] / k);
    		efs(y, x);
    	}
    	return;
    }
    
    int main() {
    	scanf("%d", &n);
    	register int xx, yy;
    	register double vv;
    	for(int i = 1; i < n; ++i) {
    		scanf("%d%d%lf", &xx, &yy, &vv);
    		vv /= 100.0;
    		add(xx, yy, vv); add(yy, xx, vv);
    	}
    	for(int i = 1; i <= n; ++i) {
    		scanf("%lf", &p[i]);
    		p[i] /= 100.0;
    	}
    	dfs(1, 0);
    	f[1] = d[1];
    	efs(1, 0);
    	for(int i = 1; i <= n; ++i) ans += 1.0 - f[i];
    	printf("%lf
    ", ans);
    	return 0;
    }
    
    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    Linux下的C编程实战之文件系统编程
    IPMSG在ubuntu linux上的安装
    NTP服务器
    [Multimedia][MPEG2]MPEG2系统原理
    BitOperation.cs
    android interview 1
    Android USB Host
    android interview 3
    someone's android note
    Android Afianl框架(1)——FinalActivity注解
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9660543.html
Copyright © 2020-2023  润新知