【[SHOI2014]概率充电器】

这是一道概率+树形\(dp\)

首先我们看到这里每一个的贡献都是1,所以我们要求的期望就是概率

求得其实就是这个

\[\sum_{i=1}^nP_i\]

\(P_i\)为节点\(i\)通电的概率

显然节点\(i\)通电有三种可能

  1. 它自己来电了
  2. 它的子树里有一个点来电了传了过来
  3. 它的子树外面有一个点来电了传了过来

第一种情况最好考虑了,至于第二种和第三种我们好像很难解决的样子

但是这显然也告诉了我们这是一个套路题,第二种和第三种正好就是树规里的\(up\) \(and\) \(down\)思想

于是我们设\(h[i]\)表示第\(i\)个节点通电的概率,之后我们利用\(up\) \(and\) \(down\)思想,在第一遍dfs的过程中,\(h[i]\)表示\(i\)通电的概率,且电一定来自它自己或者它的子树里(对应第一第二种情况),在第二遍dfs的时候被更新成为电来自于任何地方的概率(对应所有情况)

最开始初始化,\(h[i]=a[i]*0.01\)电只能来自自己

之后第一遍dfs,树形dp里的\(up\),我们要将子树的信息合并给根,由于根通电还是有两种可能

  1. 根自己来电了
  2. 儿子来电,儿子通向根的边导电

显然这两种情况只需要满足一种就够了

但是合并之后的概率是多少呢,直接加起来显然是不对的而我还真加了起来

我们考虑有两个事件\(A,B\),发生的概率分别是\(P(A),P(B)\),那么至少发生一件的概率应该是

\[P(A)+P(B)-P(A)*P(B)\]

这个怎么推出来的,很简单,至少发生一件,那么就有三种可能

  1. \(A\)发生\(B\)不发生,那么则为\(P(A)*(1-P(B))\)
  2. \(B\)发生\(A\)不发生,那么则为\(P(B)*(1-P(A))\)
  3. \(A,B\)一起发生,那么则为\(P(A)*P(B)\)

三项合起来最后一化就是\(P(A)+P(B)-P(A)*P(B)\)

所以我们合并根和子树的信息的时候,\(P(A)=h[i],P(B)=h[j]*p(i,j)\),\(i\)是子树的根,\(j\)是\(i\)的儿子,\(p(i,j)\)是这条边导电的概率

所以\(h[i]=P(A)+P(B)-P(A)*P(B)\)

之后我们就要考虑\(down\)了,一个节点有点也有可能来自它的父亲,于是我们采用\(down\)的思想用父亲更新儿子

显然我们更新一位父亲的某个儿子,显然我们只能用其他点来电传到父亲的概率来更新这个儿子

于是我们设\(P(B)=h[j]*p(i,j)\),而且有

\[P(A)+P(B)-P(A)*P(B)=h[i]\]

我们要求的是\(P(A)\)即除了\(j\)这棵子树其他点来电使得\(i\)有电的概率

于是解一下这个方程

\[P(A)-P(A)*P(B)=h[i]-P(B)\]

\[P(A)*(1-P(B))=h[i]-P(B)\]

\[P(A)=\frac{h[i]-P(B)}{1-P(B)}\]

而之后我们去更新儿子的话还有一边是否导电需要考虑,于是

\[h[j]=h[j]+(P(A)*p(i,j))-h[j]*P(A)*p(i,j)\]

之后就没有啦,同时还有一个非常坑的地方就是如果\(P(B)=h[j]*p(i,j)=1\)

那么除以\(1-P(B)\)肯定会出错,由于\(h[j]\)都已经是1了,显然没有什么必要去更新它了,于是可以直接跳过这一层接着往下更新就好了

#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define maxn 500005
#define eps 1e-7
struct node
{
    int v,nxt,w;
}e[maxn<<1];
int num,n,m;
int a[maxn],head[maxn],deep[maxn];
double h[maxn];
double ans;
inline int read()
{
    char c=getchar();
    int x=0;
    while(c<‘0‘||c>‘9‘) c=getchar();
    while(c>=‘0‘&&c<=‘9‘)
      x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}
inline void add_edge(int x,int y,int z)
{
    e[++num].v=y;
    e[num].nxt=head[x];
    e[num].w=z;
    head[x]=num;
}
void dfs(int x)//up
{
    for(re int i=head[x];i;i=e[i].nxt)
    if(!deep[e[i].v])
    {
        deep[e[i].v]=deep[x]+1;
        dfs(e[i].v);
        double k=h[e[i].v]*double(e[i].w)/100;
        h[x]=h[x]+k-h[x]*k;
    }
}
inline int check(double aa,double bb)
{
    if(aa+eps>bb&&aa-eps<bb) return 1;
    return 0;
}
void redfs(int x)//down
{
    ans+=h[x];
    for(re int i=head[x];i;i=e[i].nxt)
    if(deep[e[i].v]>deep[x])
    {
        if(check(h[e[i].v]*double(e[i].w)/100,1))
        {
            redfs(e[i].v);
            continue;
        }
        double k=(h[x]-h[e[i].v]*double(e[i].w)/100)/(1-h[e[i].v]*double(e[i].w)/100);
        k*=double(e[i].w)/100;
        h[e[i].v]=h[e[i].v]+k-k*h[e[i].v];
        redfs(e[i].v);
    }
}
int main()
{
    n=read();
    int x,y,z;
    for(re int i=1;i<n;i++)
    {
        x=read();
        y=read();
        z=read();
        add_edge(x,y,z),add_edge(y,x,z);
    }
    for(re int i=1;i<=n;i++)
        a[i]=read(),h[i]=a[i]*0.01;
    deep[1]=1;
    dfs(1);
    redfs(1);
    printf("%.6lf",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/asuldb/p/10206237.html

时间: 2024-08-29 05:51:32

【[SHOI2014]概率充电器】的相关文章

bzoj 3566: [SHOI2014]概率充电器 树形DP

首先普及一个概率公式 P(A+B)=P(A)+P(B)-P(AB) 题意:一些充电元件和导线构成一棵树,充电元件是否能充电有2种情况, 1.它自己有qi%的概率充电 2.与它相邻的元件通过导线给它充电(导线有p%的概率导通) 求最终充了电的元件的期望 题解:首先可以将元件能否充电分成3种情况考虑, 1.它自己给自己充好了电 2.它的儿子方向给它传送了电 3.它的父亲方向给它传送了电. 对于1,题目已经给出可以直接赋值, 对于2,可以通过一次树的深度遍历求得.pson[now]=pson[now]

[SHOI2014]概率充电器

[SHOI2014]概率充电器 题目 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!”SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定.随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电.作为 S

【BZOJ】3566: [SHOI2014]概率充电器

[算法]树型DP+期望DP [题意]一棵树上每个点均有直接充电概率qi%,每条边有导电概率pi%,问期望有多少结点处于充电状态? [题解]引用自:[BZOJ3566][SHOI2014]概率充电器 树形DP 概率DP by 空灰冰魂 最大的难点在于计算每个点充电期望时,两个节点各自的期望都会影响对方的期望. 所以考虑转化对象,改为求每个节点充不上电的期望,充不上电就不用考虑两者的相互影响. fi表示结点i由子结点和自身充不上电的概率 gi表示结点i由父结点充不上电的概率 第一次DFS: hi表示

Bzoj3566 [SHOI2014]概率充电器

Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 999  Solved: 428 Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!”SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元

bzoj 3566: [SHOI2014]概率充电器

Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器:"采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!"SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定.随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电.作为 SHO

【bzoj3566】[SHOI2014]概率充电器 树形概率dp

题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品——概率充电器:“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!”SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定.随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电.作为 SHOI 公司的忠实客户,你无

P4284 [SHOI2014]概率充电器

链接:https://www.luogu.org/problemnew/show/P4284 题目描述 著名的电子产品品牌SHOI 刚刚发布了引领世界潮流的下一代电子产品-- 概率充电器: "采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决 定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看 吧!" SHOI 概率充电器由n-1 条导线连通了n 个充电元件.进行充电时,每条导 线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率 决

BZOJ 3566 SHOI2014 概率充电器 树形期望DP

题目大意:给定一棵树,每个点初始有一个概率为1,为1的节点会沿着边以边权上的概率向四周扩散,求最终期望有多少个点是1 OTZ 不想写题解了贴个代码吧= = 如果有不明白做法的直接问我就好了= = #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 #define EPS 1e-7 using namespace std;

●BZOJ 3566 [SHOI2014]概率充电器

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3566题解: 概率dp,树形dp 如果求出每个点被通电的概率t, 那么期望答案就是t1×1+t2×1+t3*1+...+tn×1 现在问题就是要去求每个点被通电的概率. 因为是一颗树,所以每个点是否通电只由三个因素决定: 自己给自己通电;儿子给自己通电;父亲给自己通电. 这里采取求反面的方法: 对于每个点u, 1.求出u所在的子树不能给u点通电的概率f[u]. 2.求出u的父亲不能给u点通电