2018.08.31 bzoj3566: [SHOI2014]概率充电器(概率dp+容斥原理)

32 篇文章 0 订阅
11 篇文章 0 订阅

传送门
概率dp好题啊。
f[i] f [ i ] 表示i自己不亮并且子树中的节点不会让i亮的概率。
g[i] g [ i ] 表示i的子树以外的连通块不会使i变亮的概率。
貌似 f[i] f [ i ] 可以直接推出来啊:
f[i]=(1q[i])v(f[v]+(1f[v])(1dis[i,v])) f [ i ] = ( 1 − q [ i ] ) ∗ ∏ v ( f [ v ] + ( 1 − f [ v ] ) ∗ ( 1 − d i s [ i , v ] ) )
g[i] g [ i ] 感觉有点难推啊。
有个坑点是我们在推g[i]的时候已经自动默认i为根的子树没亮了,因此要除一个f[i]。
然后就没啥了。
我们设一个临时变量tmp。
tmp=g[fa[i]]f[fa[i]]/(f[i]+(1f[i])(1dis[fa[i],i])) t m p = g [ f a [ i ] ] ∗ f [ f a [ i ] ] / ( f [ i ] + ( 1 − f [ i ] ) ∗ ( 1 − d i s [ f a [ i ] , i ] ) )
g[i]=tmp+(1tmp)(1dis[fa[i],i]) g [ i ] = t m p + ( 1 − t m p ) ∗ ( 1 − d i s [ f a [ i ] , i ] )
代码:

#include<bits/stdc++.h>
#define N 500005
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
int n,first[N],cnt=0;
double p[N],f[N],g[N];
struct edge{int v,next;double w;}e[N<<1];
inline void add(int u,int v,double w){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].w=w,first[u]=cnt;}
inline void dfs1(int x,int fa){
    f[x]=1-p[x];
    for(int i=first[x];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        dfs1(v,x),f[x]*=f[v]+(1-f[v])*(1-e[i].w);
    }
}
inline void dfs2(int x,int fa){
    if(x==1)g[x]=1;
    for(int i=first[x];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        double tmp=g[x]*f[x]/(f[v]+(1-f[v])*(1-e[i].w));
        g[v]=tmp+(1-tmp)*(1-e[i].w);
        dfs2(v,x);
    }
}
int main(){
    n=read();
    for(int i=1;i<n;++i){
        int u=read(),v=read();
        double w=read()*1.0/100;
        add(u,v,w),add(v,u,w);
    }
    for(int i=1;i<=n;++i)p[i]=read()*1.0/100;
    dfs1(1,0),dfs2(1,0);
    double ans=0;
    for(int i=1;i<=n;++i)ans+=1-g[i]*f[i];
    printf("%.6lf",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值