概率充电器(shoi2014)

24 篇文章 0 订阅
16 篇文章 0 订阅
本文介绍了SHOI公司发布的概率充电器,该设备的导线和元件能否通电由真随机数决定。用户需要计算充电元件进入充电状态的个数的期望值。题目提供输入格式和样例,并给出了数据规模限制。
摘要由CSDN通过智能技术生成

出处[辗转山河弋流歌 by 空灰冰魂]
著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定! SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看 吧!”SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件。进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率 决定。随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电。作为 SHOI 公司的忠实客户,你无法抑制自己购买 SHOI 产品的冲动。在排了一个星期的长队之后终于入手了最新型号的 SHOI 概率充电器。你迫不及待 地将 SHOI 概率充电器插入电源——这时你突然想知道,进入充电状态的元件个数的期望是多少呢?输入第一行一个整数: n n n。概率充电器的充电元件个数。充电元件由 1 − n 1-n 1n 编号。之后的 n-1 行每行三个整数 a , b , p a, b, p a,b,p,描述了一根导线连接了编号为 a a a b b b 的充电元件,通电概率为 p%。第 n + 2 n+2 n+2 n n n 个整数: q i qi qi。表示 i 号元件直接充电的概率为 qi%。输出输出一行一个实数,为能进入充电状态的元件个数的期望,四舍五入到小数点后 6 位小数。

样例输入1
3
1 2 50
1 3 50
50 0 0
样例输出1
1.000000
样例输入1
5 
1 2 90
1 3 80
1 4 70
1 5 60
100 10 20 30 40
样例输出2
4.300000                            
提示

【数据规模】对于 30%的数据, n≤5000。对于 100%的数据, n≤500000, 0≤p,qi≤100。

CODE
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
struct fjy{
 int nxt,v;
 double w;
}e[N<<1];
int cnt,fir[N],fa[N];
double p[N],h[N],g[N],ans=0.0;//p[i]表示以i为根的子树中通电节点的期望值,g[i]表示i的父节点对i的通电节点个数期望的贡献,h[i]表示以i为根结点的子树对i的父节点通电节点个数期望的贡献 
void add(int u,int v,double w){
 e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=fir[u];fir[u]=cnt;
}
int ui,vi,wi,c,n;
void dfs1(int u,int f){
 fa[u]=f;
 for(int i=fir[u];i;i=e[i].nxt){
  if(e[i].v==f) continue;
  dfs1(e[i].v,u);
  h[e[i].v]=p[e[i].v]+(1.00-p[e[i].v])*(1-e[i].w);//由于对父节点做的贡献需要统计完过后再做,故在处理父节点时计算
  p[u]*=h[e[i].v]; 
 }
}
void dfs(int u,int f){
 ans+=1.0-p[u]*g[u];
 for(int i=fir[u];i;i=e[i].nxt){
  if(e[i].v==fa[u]) continue;
  double t=h[e[i].v]<1e-6?0.0:g[u]*p[u]/h[e[i].v]; 
  g[e[i].v]=t+(1.0-t)*(1.0-e[i].w);
  dfs(e[i].v,u);
 }
}
int main(){
 int size=100<<20;
 __asm__("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//此处要开手工栈 
 scanf("%d",&n);
 for(int i=1;i<n;i++){
  scanf("%d%d%d",&ui,&vi,&wi);
  add(ui,vi,wi/100.0),add(vi,ui,wi/100.0);
 }
 for(int i=1;i<=n;i++){
  scanf("%d",&c);
  p[i]=double(1.0-c/100.0);
 }
 dfs1(1,0); g[1]=1.0;
 dfs(1,0);
 //for(int i=1;i<=n;i++) ans+=1-p[i]*g[i];
 printf("%.6lf",ans);
 exit(0);//开手工栈无法用return退出
 return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值