【BZOJ3566】概率充电器,树形概率DP

Time:2016.08.25
Author:xiaoyimi
转载注明出处谢谢


传送门
思路:
一开始我连暴力都打不对
答案就是 Pi i=1..n
P表示每个点被通电的概率
如果把题目中的树转化成有根树,那么这个充电概率P就等于
PPW(>)PW(>
前两项比较好弄,一个是题目给出的,一个可以 O(n) 遍历通过
P(AB)=P(A)+P(B)P(AB) 计算出来的
后一项要涉及到容斥,考虑当前点为v,父亲为u,在计算父亲充电概率时的具体式子是

Pu=Pu+Pvw(u,v)PuPvw(u,v)

其中 Pu 表示除v以外,u的儿子对 Pu 的贡献
再想想我们要计算什么?
父亲对儿子的贡献,即u对v的贡献
显然此时v不能有电,也就是要把 Pv 的贡献去掉,用 Pu 来计算
化简上式就可以得到
Pu=PuPvw(u,v)1Pvw(u,v)

所以再遍历一遍就可以了
复杂度 O(n)
值得注意的是精度问题,以及如果 1Pvw(u,v)=0 那么 w(u,v)=Pv=Pu=1
那么最终概率就是1了
代码:

#include<cstdio>
#include<cmath>
#define M 500001
using namespace std;
int n,tot=1,x,y;
double z;
int first[M];
double f[M];
int in()
{
    char ch=getchar();int t=0;
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+ch-48,ch=getchar();
    return t;
}
struct edge{
    int u,v,next;
    double w;
}e[M<<1];
void add(int x,int y,double z)
{
    e[++tot]=(edge){x,y,first[x],z};first[x]=tot;
    e[++tot]=(edge){y,x,first[y],z};first[y]=tot;
}
void dfs1(int x,int fa)
{
    for (int i=first[x];i;i=e[i].next)
        if (e[i].v!=fa)
            dfs1(e[i].v,x),
            f[x]=f[x]+f[e[i].v]*e[i].w-f[x]*f[e[i].v]*e[i].w;   
}
void dfs2(int x,int fa)
{
    double tt;
    for (int i=first[x];i;i=e[i].next)
        if (e[i].v!=fa)
        {
            if (fabs(1-e[i].w*f[e[i].v])>1e-6)
                tt=(f[x]-f[e[i].v]*e[i].w)/(1-e[i].w*f[e[i].v]),
                f[e[i].v]=f[e[i].v]+tt*e[i].w-f[e[i].v]*tt*e[i].w;
            else f[e[i].v]=1;
            dfs2(e[i].v,x);
        }
}
main()
{
    n=in();
    for (int i=1;i<n;++i)
        x=in(),y=in(),z=in()/100.0,
        add(x,y,z);
    for (int i=1;i<=n;i++) f[i]=in()/100.0;
    dfs1(1,0);
    dfs2(1,0);
    for (int i=1;i<=n;i++) f[0]+=f[i];
    printf("%lf",f[0]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值