[bzoj3566]概率充电器

[bzoj3566]概率充电器


就是一个树形dp,然后注意能充电的概率是没法直接乘的所以考虑去算不能充电的概率

自己写的状态转移十分鬼畜不要在意,注意把除0判掉

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
typedef long double db;
int n,cnt,hed[N],to[N<<1],nxt[N<<1];
db pos[N<<1];
inline void adde(int u,int v,int p){
    ++cnt;to[cnt]=v,nxt[cnt]=hed[u],pos[cnt]=(double)p/100.0;hed[u]=cnt;
}
db f[N];
db P[N];
inline void dfs1(int x,int pre){
    f[x]=1.00-P[x];//没电的概率
    for(int i=hed[x];i;i=nxt[i]){
        int v=to[i];
        if(v==pre)continue;
        dfs1(v,x);
        f[x]*=1.00-(1.00-f[v])*pos[i];
    }
}

inline void dp(int x,int pre){
    for(int i=hed[x];i;i=nxt[i]){
        int v=to[i];
        if(v==pre)continue;
        if((1.00-(1.00-f[v])*pos[i])!=0)f[v]*=1.00-pos[i]*(1.00-f[x]/(1.00-(1.00-f[v])*pos[i]));
        dp(v,x);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int u,v,p;scanf("%d%d%d",&u,&v,&p);
        adde(u,v,p);adde(v,u,p);
    }
    for(int i=1;i<=n;i++){
        int p;scanf("%d",&p);
        P[i]=(db)p/100.00;
    }
    dfs1(1,0);
    dp(1,0);
    db ans=0;
    for(int i=1;i<=n;i++)
        ans+=1.00-f[i];
    printf("%.6Lf",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/83189262