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. 重温CLR(四)基元类型、引用类型、值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到framework类型(fcl)中存在的类型. 下表列出fcl类型 从另一个角度,可以认为C ...

  2. 浅谈Sql各种join的用法

    1.left join.right join.inner join三者区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右 ...

  3. Oracle 11G RAC:生产环境下架构

    转: it168网站  原创 作者:刘炳林 在真实环境搭建一套Oracle RAC就好比是一堂劳动课,劳动前需要准备好劳动工具,对劳动课内容有充分的认识;按照步骤一步一步进行,需要考虑劳动过程中可能遇 ...

  4. bzoj 2259 [Oibh]新型计算机 ——最短路(建图)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2259 不是 n^2 条边!连那条边权为0的边之后,只要每个位置向它的前一个位置和后一个位置连 ...

  5. 异常:org.springframework.http.converter.HttpMessageNotReadableException

    spring(springboot.springmvc)出现标题的异常一般是由于controller的入参失败引起的. 介绍下常规入参的两种格式: ,这种方式的入参主要是接受key-value的参数, ...

  6. POJ2226(最小顶点覆盖)

    Muddy Fields Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10044   Accepted: 3743 Des ...

  7. 文件操作之增删改查3---文件的修改,f.replace(),在linux里的一些应用sed,with语句方法来打开一个或多个文件避免忘记关闭,python一行写的太长,怎么编写多行的规范

    f.replace()with open("xxx","r",encoding="utf-8") as f: 想修改文件中间的数据,有两个办 ...

  8. php爬虫神器cURL

    cURL 网页资源(编写网页爬虫) 接口资源 ftp服务器文件资源 其他资源 static public function curl($url, $data = array(), $timeout = ...

  9. MMU_段式映射

    首先, 段式映射的示意图如下: 该例程有5个文件构成: head.s-------------入口程序 mmu.lds-----------连接文件 init.c---------------初始化文 ...

  10. mul 指令

    mul 是乘法指令 两个相乘的数:两个相乘的数,要么都是 8 位,要么都是 16 位. 如果是 8 位,一个默认放在 AL 中,另一个放在 8 位寄存器或内存字节单元中: 如果是 16 位,一个默认在 ...