• Luogu4284 [SHOI2014]概率充电器


    Description

    link

    (n(nle 5 imes10^5)) 个元件 和 (n-1) 条充电线,每个电线有一定概率通电,每个元件有一定概率自己有电,求有电的元件的期望个数

    Solution

    当前原件 (x) 充电的概率 (f_x)

    [sum_{(x,y)in E} f_y imes p_{x,y}+ d_x ]

    考虑高斯消元,时间复杂度 (O(n^3))

    期望得分?(O(n^3))(5 imes10^5)

    发现这是一棵树,并不是一张图,所以考虑换根法

    定义 (f_{i}) 为当前点的通电概率

    那么 (ans=sumlimits_{i=1}^n f_i)

    这题目的最大收获

    概率与概率相互独立,计算时可以考虑 (f_{i}=(1-f_{i}) imes calc(t))

    这样可以避免 (f_i >1) 的情况

    子树里面的很套路,关键是子树外面的(这里我一开始卡了好久好久)

    [f_{t}=frac{(f_{x}-f_{t} imes p_{x,t})}{1-f_t imes p_{x,t}} imes(1-f_t) imes p_{x,t} ]

    其实没想到的是分母的部分,直接拆掉组成所占比例除一下挺妙的

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define reg register
    #define For(i,a,b) for(reg int i=a;i<=b;++i)
    #define Down(i,a,b) for(reg int i=a;i>=b;--i)
    namespace yspm{
        inline int read()
        {
            int res=0,f=1; char k;
            while(!isdigit(k=getchar())) if(k=='-') f=-1;
            while(isdigit(k)) res=res*10+k-'0',k=getchar();
            return res*f;
        }
        const int N=5e5+10;
        struct node{
            int to,nxt; double p;
        }e[N<<1];
        int head[N],cnt,n;
        inline void add(int u,int v,double p)
        {
            e[++cnt].to=v; e[cnt].nxt=head[u]; e[cnt].p=p/100;
            return head[u]=cnt,void();
        }
        double f[N],ans;
        inline void dfs1(int x,int fa)
        {
            for(int i=head[x];i;i=e[i].nxt)
            {
                int t=e[i].to; if(t==fa) continue;
                dfs1(t,x); f[x]+=f[t]*e[i].p*(1-f[x]);
            }
            return ;
        }
        inline void dfs2(int x,int fa)
        {
            for(int i=head[x];i;i=e[i].nxt)
            {
                int t=e[i].to; if(t==fa) continue;
                if(f[t]*e[i].p!=1) f[t]+=(1-f[t])*(f[x]-f[t]*e[i].p)/(1-f[t]*e[i].p)*e[i].p;
                dfs2(t,x);
            }return ;
        }
        signed main()
        {
            n=read(); For(i,1,n-1){int u=read(),v=read(),w=read(); add(u,v,w),add(v,u,w);}   
            For(i,1,n) f[i]=1.0*read()/100; 
            dfs1(1,0); dfs2(1,0); 
            For(i,1,n) ans+=f[i];
            printf("%.6lf
    ",ans);
            return 0;
        }
    }signed main(){return yspm::main();}
    
  • 相关阅读:
    MySQL数据库常见面试题
    抽象类与接口
    HashMap与Hashtable的区别
    IDEA破解
    重写equals方法
    MFC编程入门之十七(对话框:文件对话框)
    MFC编程入门之十六(对话框:消息对话框)
    MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)
    MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)
    MFC编程入门之十二(对话框:非模态对话框的创建及显示)
  • 原文地址:https://www.cnblogs.com/yspm/p/13621040.html
Copyright © 2020-2023  润新知