• Loj #2192. 「SHOI2014」概率充电器


    Loj #2192. 「SHOI2014」概率充电器

    题目描述

    著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:

    「采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生

    活不可或缺的必需品!能充上电吗?现在就试试看吧!」

    SHOI 概率充电器由 (n-1) 条导线连通了 (n) 个充电元件。进行充电时,每条导线是否可以导电以

    概率决定,每一个充电元件自身是否直接进行充电也由概率决定。随后电能可以从直接充电的元件经过

    通电的导线使得其他充电元件进行间接充电。

    作为 SHOI 公司的忠实客户,你无法抑制自己购买 SHOI 产品的冲动。在排了一个星期的长队之后终

    于入手了最新型号的 SHOI 概率充电器。你迫不及待地将 SHOI 概率充电器插入电源——这时你突然想

    知道,进入充电状态的元件个数的期望是多少呢?

    输入格式

    第一行一个整数 (n),概率充电器的充电元件个数,充电元件由 (1 sim n) 编号。

    之后的 (n-1) 行每行三个整数 (a, b, p),描述了一根导线连接了编号为 (a)(b) 的充电元

    件,通电概率为 (p\, \%)

    (n+2)(n) 个整数 (q_1,ldots,q_n)。表示 (i) 号元件直接充电的概率为 (q_i\, \%)

    输出格式

    输出一行一个实数,为进入充电状态的元件个数的期望,四舍五入到六位小数。

    数据范围与提示

    对于 (100\%) 的数据,(n leq 500000, 0 leq p,q_i leq 100)

    (\)

    根据期望的线性性,我们统计每个点通电出现的概率。发现统计每个点不通电的概率好统计些,也就是该点所在联通块一个点都不通电。

    上下两次树形(DP)就搞定了。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 500005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    int n;
    struct road {
    	int to,nxt;
    	double p;
    }s[N<<1];
    
    int h[N],cnt;
    void add(int i,int j,double p) {
    	s[++cnt]=(road) {j,h[i],p};h[i]=cnt;
    }
    
    double f[N];
    double up[N];
    double q[N];
    
    void dfs(int v,int fr) {
    	f[v]=1-q[v];
    	for(int i=h[v];i;i=s[i].nxt) {
    		int to=s[i].to;
    		if(to==fr) continue ;
    		dfs(to,v);
    		f[v]=f[v]*(s[i].p*f[to]+(1.0-s[i].p));
    	}
    }
    
    double pre[N],suf[N];
    double ans;
    void dfs2(int v,int fr) {
    	ans+=1.0-f[v]*up[v];
    	vector<int>tem;
    	vector<double>E;
    	tem.clear();
    	E.clear();
    	for(int i=h[v];i;i=s[i].nxt) {
    		int to=s[i].to;
    		if(to==fr) continue ;
    		tem.push_back(to);
    		E.push_back(s[i].p);
    		suf[to]=pre[to]=s[i].p*f[to]+(1.0-s[i].p);
    	}
    	for(int i=1;i<tem.size();i++) pre[tem[i]]=pre[tem[i]]*pre[tem[i-1]];
    	for(int i=tem.size()-2;i>=0;i--) suf[tem[i]]=suf[tem[i]]*suf[tem[i+1]];
    	for(int i=0;i<tem.size();i++) {
    		int to=tem[i];
    		double now=1;
    		if(i>0) now=now*pre[tem[i-1]];
    		if(i<tem.size()-1) now=now*suf[tem[i+1]];
    		up[to]=up[v]*now*(1.0-q[v])*E[i]+(1.0-E[i]);
    		dfs2(to,v);
    	}
    }
    
    int main() {
    	n=Get();
    	int a,b,p;
    	for(int i=1;i<n;i++) {
    		a=Get(),b=Get(),p=Get();
    		add(a,b,1.0*p/100);
    		add(b,a,1.0*p/100);
    	}
    	for(int i=1;i<=n;i++) q[i]=1.0*Get()/100;
    	dfs(1,0);
    	up[1]=1;
    	dfs2(1,0);
    	cout<<fixed<<setprecision(6)<<ans;
    	return 0;
    }
    
    
  • 相关阅读:
    手把手带你玩转 DialogFragment
    紧张的去京东面试7,没想到可以成功拿下offer
    这个有点强,MySQL常用优化指南及大表优化思路(值得收藏)
    Java程序员两年经验斩获头条 Offer,技术杠杠的
    为什么大家都说 SELECT * 效率低
    Java程序员想要靠外包刷题,结果却大跌眼镜,心态都崩了
    一次请求在SpringMVC核心执行流程
    工作三年经验,一年内我靠这份javaBAT进阶面试题从13K到大厂25K
    用了这么久的数据库连接池,你知道原理吗?
    poj 3295 Tautology(栈)
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10792065.html
Copyright © 2020-2023  润新知