这是一道告诉我概率没有想象中那么难的题.....

首先,用期望的线性性质,那么答案为所有点有电的概率和

发现一个点的有电的概率来源形成了一个"或"关系,在概率中,这并不好计算...(其实是可以算的,只不过式子要复杂点...)

考虑反面,一个点没电的概率来源是一个“与”关系,比较好计算

举个荔枝,有$A, B, C$三个变量,$A, B, C$分别有$0.5, 0.3, 0.2$的概率为$1$

问$A | B | C$为$1$的概率?

如果,我们从正面考虑,那么答案为$0.5 + (1 - 0.5) * 0.3 + (1 - 0.5 - (1 - 0.5) * 0.3) * 0.2 = 0.72$

但是,如果从反面考虑,那么答案为$1 - (1 - 0.2)(1 - 0.3)(1 - 0.5) = 0.72$

从这个荔枝可以看出,概率中“或”很难算,“与”比较好算(其实求解$| = !\&!$)

那么,考虑一个点没电,大体上分为子树不给电和父亲不给电两种情况

分别来考虑:

记$i$自己用爱发电的概率为$e_i$,边$(u, v)$用爱发电的概率为$e(u, v)$

设子树内不给$u$充电的概率为$f[u]$,那么$f[u] = (1 - e_i) * \prod_{v \in son_u} f[v] + (1 - f[v]) * (1 - e(u, v))$

再来考虑父亲不给电

设父亲不给$u$充电的为$g[u]$,那么有$g[u] = g[fa] + (1 - g[fa])(1 - e(u, fa))$

那么,求解$g[fa]$就成了一个问题,如果我们在$O(n ^2 )$的时间内求出所有的$g[fa]$,那么我们就能在$O(n ^ 2)$求出所有的$f$

在$O(n ^ 2)$的时间内求出$g[fa]$,自然是不难的,发现这是一个以$fa$为根的$dp$

对于一个节点,$f[u] *g[u]$就是答案

进一步分析,发现其实求$g[fa]$的时候非常的状态是重复的,能不能优化呢?

当然是可以的,画个美妙的图

那么,注意到以$fa$为根的子树包括$gf$的子树和$fa$除了$u$以外的子树

那么,只要能快速地调用除了$u$以外的所有子树转移值得乘积,就能解决左边的子树

同时,右边的子树可以调用$g[gf]$来快速转移

然后就是$O(n)$啦!

代码好像还加了点优化

年代久远了,忘了是什么优化了...

#include <cstdio>
#define dl double
#define sid 500050
#define ri register int
using namespace std; char RR[];
extern inline char gc() {
static char *S = RR + , *T = RR + ;
if(S == T) fread(RR, , , stdin), S = RR;
return *S ++;
}
inline int read() {
int p = , w = ; char c = gc();
while(c > '' || c < '') { if(c == '-') w = -; c = gc(); }
while(c >= '' && c <= '') { p = p * + c - ''; c = gc(); }
return p * w;
} int n, cnt;
dl a[sid], s[sid], f[sid], pi[sid * ];
int cap[sid], node[sid * ], nxt[sid * ]; void addedge(int u, int v, dl p) {
nxt[++ cnt] = cap[u]; cap[u] = cnt;
node[cnt] = v; pi[cnt] = 1.0 - p;
} void son_fa(int e, int fa) {
s[e] = - a[e];
for(int i = cap[e]; i; i = nxt[i]) {
int d = node[i];
if(fa == d) continue;
son_fa(d, e);
s[e] *= s[d] + ( - s[d]) * pi[i];
}
} void fa_son(int e, int fa) {
for(int i = cap[e]; i; i = nxt[i]) {
int d = node[i];
if(d == fa) continue;
dl P = f[e] / (s[d] + ( - s[d]) * pi[i]);
f[d] = (P + ( - P) * pi[i]) * s[d];
fa_son(d, e);
}
} int main() {
n = read();
for(ri i = ; i < n; i ++) {
int u = read(), v = read(), p = read();
addedge(u, v, p / 100.0); addedge(v, u, p / 100.0);
}
for(ri i = ; i <= n; i ++) {
int p = read();
a[i] = p / 100.0;
}
son_fa(, );
f[] = s[];
fa_son(, );
dl ans = ;
for(ri i = ; i <= n; i ++) ans += - f[i];
printf("%.6lf\n", ans);
return ;
}

luoguP4284 [SHOI2014]概率充电器 概率期望树形DP的更多相关文章

  1. [BZOJ3566][SHOI2014]概率充电器 换根树形DP

    链接 题意:n个充电元件形成一棵树,每个点和每条边都有各自的充电概率,元件可以自身充电或者通过其他点和边间接充电,求充电状态元件的期望个数 题解 设1为根节点 设 \(f[x]\) 表示 \(x\) ...

  2. 洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP

    洛谷 P4284 [SHOI2014]概率充电器 概率与期望+换根DP 题目描述 著名的电子产品品牌\(SHOI\) 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米 ...

  3. 【BZOJ3566】[SHOI2014]概率充电器 期望+树形DP

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

  4. [BZOJ3566][SHOI2014]概率充电器(概率DP)

    题意:树上每个点有概率有电,每条边有概率导电,求每个点能被通到电的概率. 较为套路但不好想的概率DP. 树形DP肯定先只考虑子树,自然的想法是f[i]表示i在只考虑i子树时,能有电的概率,但发现无法转 ...

  5. 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP

    好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...

  6. luogu P3412 仓鼠找sugar II 期望 树形dp

    LINK:仓鼠找sugar II 以前做过类似的期望题目 加上最后的树形dp不算太难 还是可以推出来的. 容易发现 当固定起点和终点的时候 可以先固定根 这样就不用分到底是正着走还是倒着走了. 1为根 ...

  7. bzoj 3566: [SHOI2014]概率充电器 数学期望+换根dp

    题意:给定一颗树,树上每个点通电概率为 $q[i]$%,每条边通电的概率为 $p[i]$%,求期望充入电的点的个数. 期望在任何时候都具有线性性,所以可以分别求每个点通电的概率(这种情况下期望=概率 ...

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

    BZOJ 洛谷 这里写的不错,虽然基本还是自己看转移... 每个点的贡献都是\(1\),所以直接求每个点通电的概率\(F_i\),答案就是\(\sum F_i\). 把\(F_x\)分成:父节点通电给 ...

  9. [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)

    题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才.        ...

随机推荐

  1. [Swing]树形结构的实现

    一般步骤: 1.建立根节点 private DefaultMutableTreeNode root = new DefaultMutableTreeNode("根节点"); 2.建 ...

  2. 面向对象 ( OO ) 的程序设计——继承

    本文地址:http://www.cnblogs.com/veinyin/p/7608282.html  仅支持实现继承,且主要依靠原型链来实现,不过一般会混合构造函数一起实现继承 1 原型链 继承使用 ...

  3. CodeForces - 999C

    You are given a string ss consisting of nn lowercase Latin letters. Polycarp wants to remove exactly ...

  4. vue-cli使用说明

    一.安装npm install -g vue-cli 推荐使用国内镜像 先设置cnpm npm install -g cnpm --registry=https://registry.npm.taob ...

  5. hdu 5319 Painter(杭电多校赛第三场)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5319 Painter Time Limit: 2000/1000 MS (Java/Others)   ...

  6. localStorage H5本地存储

    域内安全.永久保存.即客户端或浏览器中来自同一域名的所有页面都可访问localStorage数据且数据除了删除否则永久保存,但客户端或浏览器之间的数据相互独立. <!doctype html&g ...

  7. THINKPHP简单商品查询项目

    代码:http://files.cnblogs.com/files/wordblog/test.zip

  8. Function.prototype.bind 简介

    bind可以解决两种问题: 1. 可以改变一个函数的 this 指向 2. 可以实现偏函数等高阶功能 本文暂且讨论第一个功能 USE CASE var foo = { x: 3 } var bar = ...

  9. C++之 extern C的作用详解

    extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码.加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C+ ...

  10. python中的pydoc

    在终端上输入pydoc会显示以下信息 pydoc - the Python documentation tool pydoc <name> ... Show text documentat ...