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( ...
随机推荐
- MongoDB 学习手册 - 安装(windwos 环境)
- Django学习手册 - 权限管理(一)
权限管理原理: 不同角色拥有不同的角色权限,所以能否访问的页面也就不相同. 通过控制URL使用户访问到不同的URL,从而达到权限控制的目的. 设计权限数据库 权限管理 from django.db i ...
- nginx 模块配置
第一个 当前活跃的连接数 nginx握手的数 连接数 总的请求数
- listView从底部回到顶部代码实现
可用如下方法: 1.平滑的回到顶部,但是会划过中间的每一页 mListView.getRefreshableView().smoothScrollToPosition(0); 2.直接跳到顶部 if ...
- CF1100F Ivan and Burgers
题目地址:CF1100F Ivan and Burgers 一道有难度的线性基题,看了题解才会做 预处理两个数组: \(p_{r,i}\) 表示满足下列条件的最大的 \(l\) :线性基第 \(i\) ...
- 如何能让MAC和PC都能读写移动硬盘
Macbook Pro 移动硬盘 希捷硬盘就不用,有专业适用于苹果的软件. 1.在“LaunchPad”中找到并打开“磁盘工具”,在“磁盘工具”中可以看到移动硬盘的几个分区 2.选择一个分区后,选择“ ...
- go语言time包的学习(Time,Location,Duration,Timer,Ticker)
package main; import ( "time" "fmt" ) func main() { //time.Time代 ...
- Spring HibernateTemplate与HibernateDaoSupport对比
HibernateTemplate与HibernateDaoSupport两者都是spring整合hibernate提供的模板技术. 对于保存一个对象,HibernateTemplate需要先配置 配 ...
- List元素去重的方法
l为有重复元素的列表. 方法一: 可以简单的使用l = list(set(l)) 去重 方法二: fromkeys用法:dict.fromkeys(seq[, value])),value默认是Non ...
- Media Query-响应式布局
做响应式网站的时候,一定要在页面头部加入如下的声明: <meta name="viewport" content="width=device-width, init ...