bzoj 3566
非常好也是比较难的题
首先,不难看出这是一道树形的概率dp
那么我们就要考虑转移
我们发现,一个点能充上电的概率是这个点本身通电的概率+这个点的子节点给他传过来电的概率+这个点的父节点给他传过来电的概率
但是这里的加法都是概率的加法,也就是说满足如下公式:
那么如果是三元事件,这个公式会更为复杂,所以这一点并不是特别容易计算
那么我们考虑正难则反:
一个点没有电的概率=父节点没传过来电的概率*子树内部没传过来电的概率(这里的子树内部包括子节点和这个节点本身)
所以我们用两个状态分别计算这两个概率:
设状态f[i]表示以i为根节点的子树中没有给i传过来电的概率,g[i]表示i的父节点没有给i传过来电的概率
那么显然,f[i]更容易转移,所以我们先转移f[i]
一个点的子树内部都没给他传过来电的概率,根据乘法原理,有:
解释:对于每个子节点,有两种可能向上继承:一是本身这个节点没有电,二是这个节点有电了但是连接这两点之间的边没有电
而且显然要求根节点本身不能有电,所以再乘一个根节点没有电的概率
这样第一个dfs就完成了
至于g[i]的转移,也是同理,首先,最大的根节点没有父节点,所以g[root]=1(这里root设为1)
然后从上向下更新,一个父节点不能更新子节点的情况是父节点没有通电或父节点通电了但中间的边没有通电,算一下这两部分的概率即可。
但是有个问题:我们知道,父节点没有通电的概率有一部分是由于子节点没有通电引起的,但是这里是用父节点更新子节点,这样会产生重复计算
所以我们在计算父节点没有通电的概率时要除掉子节点向父节点产生的贡献,这样才准确
所以表达式如下:
这就是第二个dfs
最后计算答案即可
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
int next;
int to;
double p;
}edge[1000005];
double ret[500005];
int head[500005];
double q[500005];
int cnt=1;
double f[500005];
double g[500005];
int n;
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void add(int l,int r,double pp)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
edge[cnt].p=pp;
head[l]=cnt++;
}
void dfs(int x,int fx)
{
f[x]=(1-q[x]);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fx)
{
continue;
}
dfs(to,x);
f[x]*=f[to]+(1.0-f[to])*(1.0-edge[i].p);
}
}
void redfs(int x,int fx)
{
for(int i=head[x];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fx)
{
continue;
}
double p0=f[x]*g[x]/(double)(f[to]+(1-f[to])*(1-edge[i].p));//父节点不通电的概率
g[to]=p0+(1-p0)*(1-edge[i].p);
redfs(to,x);
}
}
int main()
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int x,y;
double z;
scanf("%d%d%lf",&x,&y,&z);
z*=0.01;
add(x,y,z);
add(y,x,z);
}
for(int i=1;i<=n;i++)
{
scanf("%lf",&q[i]);
q[i]*=0.01;
}
dfs(1,1);
g[1]=1.0;
redfs(1,1);
double ans=0;
for(int i=1;i<=n;i++)
{
ans+=1.0-f[i]*g[i];
}
printf("%.6lf\n",ans);
return 0;
}
bzoj 3566的更多相关文章
- BZOJ 3566: [SHOI2014]概率充电器( 树形dp )
通过一次dfs求出dp(x)表示节点x考虑了x和x的子树都没成功充电的概率, dp(x) = (1-p[x])π(1 - (1-dp[son])*P(edge(x, son)).然后再dfs一次考虑节 ...
- BZOJ 3566: [SHOI2014]概率充电器 [树形DP 概率]
3566: [SHOI2014]概率充电器 题意:一棵树,每个点\(q[i]\)的概率直接充电,每条边\(p[i]\)的概率导电,电可以沿边传递使其他点间接充电.求进入充电状态的点期望个数 糖教题解传 ...
- ●BZOJ 3566 [SHOI2014]概率充电器
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3566题解: 概率dp,树形dp 如果求出每个点被通电的概率t, 那么期望答案就是t1×1+t ...
- BZOJ.3566.[SHOI2014]概率充电器(概率DP 树形DP)
BZOJ 洛谷 这里写的不错,虽然基本还是自己看转移... 每个点的贡献都是\(1\),所以直接求每个点通电的概率\(F_i\),答案就是\(\sum F_i\). 把\(F_x\)分成:父节点通电给 ...
- 【BZOJ 3566】 3566: [SHOI2014]概率充电器 (概率树形DP)
3566: [SHOI2014]概率充电器 Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电 ...
- bzoj 3566 [SHOI2014]概率充电器——树型
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3566 一眼看上去高斯消元.n^3不行. 竟然直接去看了TJ.发现树型dp.一下想到了自己还没 ...
- bzoj 3566: [SHOI2014]概率充电器
Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器:"采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率 ...
- BZOJ 3566 [SHOI2014]概率充电器 ——期望DP
期望DP. 补集转化,考虑不能被点亮的情况, 然后就是三种情况,自己不能亮,父亲不能点亮它,儿子不能点亮它. 第一次计算比较容易,第二次计算的时候需要出去第一次的影响,因为一条线只能传导一次 #inc ...
- bzoj 3566: [SHOI2014]概率充电器【树形概率dp】
设g[u]为这个点被儿子和自己充上电的概率,f[u]为被儿子.父亲和自己充上电的概率 然后根据贝叶斯公式(好像是叫这个),1.P(A+B)=P(A)+P(B)-P(A)*P(B),2.P(A)=(P( ...
随机推荐
- MySQL基本命令(待更新...)
数据库操作SQL语句 show databases; 表操作SQL语句 数据库权限操作SQL语句 参考链接 :http://www.cnblogs.com/bzys/archive/2013/01/2 ...
- 如何在 JS 中嵌入大量 HTML 代码 --更新2017-10-10 16:37:09
一.一般方式 方式1:\ 要写在标签后面,看例子 var longString = "\ ------------------------\ ------------------------ ...
- Javascript - ExtJs - 整合百度文章编辑器
ExtJs - 整合百度文章编辑器(ExtJs UEditor) 第一步:去官网下载最新版本的UEditor,UEditor下载. 第二步:在编辑器根目录创建一个Extjs-Editor.js,录入以 ...
- python基础-----类和实例
在python中,首字母大写的名称指的是类,这个类定义中括号的内容是空的. 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板而实例是根据类创建出来的一个个具体 ...
- Linux下tar压缩解压缩命令详解
tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压缩归档文件末尾追加文件-u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个.下面的 ...
- NMON使用以及nmon_analyse生成分析报表
在我们监控我们的操作系统的时候如果可以把各个硬件的监控信息生成形象化的分析报表图对于我们来说是件太好的事情了,而通过ibm的nom和nmon_analyser两者的结合完全可以实现我们的要求.首先对n ...
- 设计模式C++学习笔记之六(Facade门面模式)
Facade门面模式,也是比较常用的一种模式,基本上所有软件系统中都会用到. GOF 在<设计模式>一书中给出如下定义:为子系统中的一组接口提供一个一致的界面, Facade 模式定义 ...
- C++ 类中特殊的成员变量(常变量、引用、静态)的初始化方法
有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同.这些特殊的类型的成员变量包括: a.引用 b.常量 c.静态 d.静态常量(整型) e.静态常量(非整型) 常量和引 ...
- sonar——Synchronized classes Vector, Hashtable, Stack and StringBuffer should not be used
It is better to use their new unsynchronized replacements: ArrayList or LinkedList instead of Vector ...
- vue路由vue-router的使用
对于单页应用,官方提供了vue-router进行路由跳转的处理. 安装 基于传统,我更喜欢采用npm包的形式进行安装. npm install vue-router --save 当然,官方采用了多种 ...