1 条题解

  • 0
    @ 2025-8-24 21:58:32

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar asuldb
    哭晕了喵

    搬运于2025-08-24 21:58:32,当前版本为作者最后更新于2018-08-29 18:45:09,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这是一道概率+树形dpdp

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

    求得其实就是这个

    i=1nPi\sum_{i=1}^nP_i

    PiP_i为节点ii通电的概率

    显然节点ii通电有三种可能

    1. 它自己来电了

    2. 它的子树里有一个点来电了传了过来

    3. 它的子树外面有一个点来电了传了过来

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

    但是这显然也告诉了我们这是一个套路题,第二种和第三种正好就是树规里的upup andand downdown思想

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

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

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

    1. 根自己来电了

    2. 儿子来电,儿子通向根的边导电

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

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

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

    P(A)+P(B)P(A)P(B)P(A)+P(B)-P(A)*P(B)

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

    1. AA发生BB不发生,那么则为P(A)(1P(B))P(A)*(1-P(B))

    2. BB发生AA不发生,那么则为P(B)(1P(A))P(B)*(1-P(A))

    3. A,BA,B一起发生,那么则为P(A)P(B)P(A)*P(B)

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

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

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

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

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

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

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

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

    于是解一下这个方程

    P(A)P(A)P(B)=h[i]P(B)P(A)-P(A)*P(B)=h[i]-P(B) P(A)(1P(B))=h[i]P(B)P(A)*(1-P(B))=h[i]-P(B) P(A)=h[i]P(B)1P(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)h[j]=h[j]+(P(A)*p(i,j))-h[j]*P(A)*p(i,j)

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

    那么除以1P(B)1-P(B)肯定会出错,由于h[j]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;
    } 
    
    
    • 1

    信息

    ID
    3257
    时间
    2000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者