BZOJ 3566

树形$dp$ + 概率期望。

每一个点的贡献都是$1$,在本题中期望就等于概率。

发现每一个点要通电会在下面三件事中至少发生一件:

1、它自己通电了。

2、它的父亲给它通电了。

3、它的儿子给它通电了。

那么我们设$f_i$表示它的父亲给它通电的概率,$g_i$表示它的子树中给它通电的概率,那么最后的答案$\sum_{i = 1}^{n}f_i + g_i - f_i * g_i = \sum_{i = 1}^{n}1 - (1 - f_i) * (1 - g_i)$。

感觉好麻烦,直接把$f_i$和$g_i$设成不通电的概率好了。

先考虑计算$g$。

假设每个点$i$自己通电的概率是$a_i$,一条连接着$x$和$y$的边通电的概率是$val(x, y)$,那么$g_x = (1 - a_x)\prod_{y \in son(x)}(g_y + (1 - g_y) * (1 - val(x, y)))$。

因为如果一个点不从自己的子树中得到电,那么它自己一定没有电,然后对于每一个儿子,要么不通电,要么通了电但是这条边是不通电的,电量传递不上来。

然后考虑计算$f$,对于一对父子关系的点$(x, y)$,我们发现要么$x$不带电,要么$x$带了电但是这条边传递不过来,那么$x$不带电的概率$P = \frac{f_x * g_x}{g_y + (1 - g_y) * (1 - val(x, y))}$,

这时候我们默认$y$是不带电的,但是我们在计算$g_x$的时候多算了$y$的贡献,所以要除掉,然后$f_y = P + (1 - P) * (1 - val(x, y))$。

时间复杂度$O(n)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef double db; const int N = 5e5 + ; int n, tot = , head[N];
db a[N], f[N], g[N]; struct Edge {
int to, nxt;
db val;
} e[N << ]; inline void add(int from, int to, db val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} void dfs1(int x, int fat) {
g[x] = - a[x];
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs1(y, x);
g[x] *= (g[y] + ( - g[y]) * ( - e[i].val));
}
} void dfs2(int x, int fat, int inEdge) {
if(!fat) f[x] = 1.0;
else {
db p = g[fat] * f[fat] / (g[x] + ( - g[x]) * ( - e[inEdge].val));
f[x] = p + ( - p) * ( - e[inEdge].val);
} for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs2(y, x, i);
}
} int main() {
// freopen("2.in", "r", stdin); read(n);
for(int x, y, v, i = ; i < n; i++) {
read(x), read(y), read(v);
db val = 1.0 * v / 100.0;
add(x, y, val), add(y, x, val);
}
for(int i = ; i <= n; i++) {
int v; read(v);
a[i] = 1.0 * v / 100.0;
} dfs1(, );
dfs2(, , ); /* for(int i = 1; i <= n; i++)
printf("%f ", f[i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%f ", g[i]);
printf("\n"); */ db ans = ;
for(int i = ; i <= n; i++)
ans += ( - g[i] * f[i]); printf("%.6f\n", ans);
return ;
}

Luogu 4284 [SHOI2014]概率充电器的更多相关文章

  1. luogu P4284 [SHOI2014]概率充电器 期望 概率 树形dp

    LINK:概率充电器 大概是一个比较水的题目 不过有一些坑点. 根据期望的线性性 可以直接计算每个元件的期望 累和即为答案. 考虑统计每一个元件的概率的话 那么对其有贡献就是儿子 父亲 以及自己. 自 ...

  2. 【题解】Luogu P4284 [SHOI2014]概率充电器

    原题传送门 我们知道,每个电器充电对充电电器数的贡献都是相等的1,所以若第\(i\)个电器有\(p_i\)的概率充电时 \[E=\sum_{i=1}^np_i\] 我们考虑如何求\(p_i\),根据树 ...

  3. P4284 [SHOI2014]概率充电器

    P4284 [SHOI2014]概率充电器 今天上课讲到的题orz,第一次做这种上下搞两次dp的题. g[i]表示i的子树(包括i)不给i充电的概率. f[i]表示i的父亲不给i充电的概率. g[]可 ...

  4. BZOJ 3566: [SHOI2014]概率充电器( 树形dp )

    通过一次dfs求出dp(x)表示节点x考虑了x和x的子树都没成功充电的概率, dp(x) = (1-p[x])π(1 - (1-dp[son])*P(edge(x, son)).然后再dfs一次考虑节 ...

  5. BZOJ 3566: [SHOI2014]概率充电器 [树形DP 概率]

    3566: [SHOI2014]概率充电器 题意:一棵树,每个点\(q[i]\)的概率直接充电,每条边\(p[i]\)的概率导电,电可以沿边传递使其他点间接充电.求进入充电状态的点期望个数 糖教题解传 ...

  6. BZOJ3566: [SHOI2014]概率充电器 树形+概率dp

    3566: [SHOI2014]概率充电器 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1888  Solved: 857[Submit][Stat ...

  7. 洛谷 P4284 [SHOI2014]概率充电器 解题报告

    P4284 [SHOI2014]概率充电器 题目描述 著名的电子产品品牌SHOI 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  8. 【BZOJ 3566】 3566: [SHOI2014]概率充电器 (概率树形DP)

    3566: [SHOI2014]概率充电器 Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电 ...

  9. BZOJ3566 SHOI2014 概率充电器 【概率DP】

    BZOJ3566 SHOI2014 概率充电器 Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器: “采用全新纳米级加工技术,实现元件与导线能 ...

随机推荐

  1. 【模板】NOIP模板汇总

    图论 数据结构 数学 其他: 洛谷模板:a,b两个字符串,求b串在a串中出现的位置 #include<iostream> #include<cstdio> #include&l ...

  2. Vant async-validator 表单校验

    感谢:尤大大的 vue.有赞的 vant.async-validator.以及 asseek 链接:https://www.jianshu.com/p/d58fe749b97f 在下不才在 assee ...

  3. linux 命令详解 sort

    转自:https://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html sort是在Linux里非常常用的一个命令,管排序的,集中精力,五 ...

  4. mysql中修改密码的方式

    参考地址:https://www.cnblogs.com/yang82/p/7794712.html mysql中修改用户密码的方式: 最简单的方法就是借助第三方工具Navicat for MySQL ...

  5. Linux安装python

    1.打开终端,输入:wget https://www.python.org/ftp/python/3.5.0/Python-3.5.0b4.tgz下载完毕后 2.输入解压命令:tar –zxvf Py ...

  6. 【openCV学习笔记】【2】读取并播放一段视频

    #include <iostream> #include <opencv/highgui.h> int main(int argc, char** argv){ cvNamed ...

  7. mysql复制(高可用架构方案的基础)

    mysql复制:把一个数据库实例上所有改变复制到另外一个数据库库服务器实例的过程特点:1.没有改变就无所谓复制 ;改变是复制的根本与数据源2.所有的改变:是指可以复制全部改变,也可以复制部分改变 可以 ...

  8. Mvn+Jetty启动项目

    这里要注意,Mvn加jetty启动项目,主要用到的是Maven的jetty插件,和你下的Jetty服务器没什么关系. 我的运行环境是jdk1.7,Eclipse-mars,Maven是Eclipse自 ...

  9. 比赛安排(穷举法或dfs)

    比赛安排 时间限制: 1 Sec  内存限制: 125 MB提交: 11  解决: 10[提交][状态][讨论版][命题人:外部导入] 题目描述 设有2n(n<=6)个球队进行单循环比赛,计划在 ...

  10. Xdebug日志文件不显示

    Xdebug是一个很强大的调试php的软件,安装也很简单. 1.php_xdebug.dll 放入php目录下的ext文件中 2.php.ini中开启 [Xdebug] extension = &qu ...