1. 程式人生 > >【題解】 P4284 [SHOI2014]概率充電器

【題解】 P4284 [SHOI2014]概率充電器

const main cup 一個 space bits tin using inpu

\(Description:\)

一棵樹,每個點q[i]的概率直接充電,每條邊p[i]的概率導電,電可以沿邊傳遞使其他點間接充電。求進入充電狀態的點期望個數。

\(Sample\) \(Iuput:\)

3
1 2 50
1 3 50
50 0 0

\(Sample\) \(Input:\)

5
1 2 90
1 3 80
1 4 70
1 5 60
100 10 20 30 40

\(Solution:\)

考慮樹形dp,首先我們需要明白,其實我們要求的期望就是概率之和,那麽我們只要求出每個點的概率,那麽怎麽求每個點的概率捏?

yzc提供了一種神奇的辦法,考慮對於每個點,先求出每個點的子樹的概率和 \(f[u]\)

那麽對於一個點 \(u\),就只要讓 \(u\) 的所有兒子到他的概率取個並集,

概率並的求法:

\(P(A \cup B)=P(A)+P(B)-P(A)*P(B)\)

第一遍 \(dfs\) 求出所有的 \(f\),但這樣只是求出了當前這個點的子樹給他充電的概率,還沒有求父親給他充電的概率。

那麽再紀錄一個 \(g\),數組記錄當前的總概率,然後考慮 \(g\) 的轉移:

那麽我們考慮已經求出了他父親的 \(g[fa]\) 要求 \(g[v]\)

那麽就只要把 當前的點的子樹對 \(g[fa]\) 的貢獻給除掉就可以了。

求概率補集:

\(P(A)=\frac{P(A \cup B)-P(B)}{1-P(B)}\)

\((註意特判1-P(B)==0)\)

那麽就可以愉快的用兩次 \(dfs\) 求出答案。

#include<bits/stdc++.h>
using namespace std;
typedef double DD;
int n,En;
DD ans;
const int N=5e5+5;
inline DD unit(DD a,DD b){
    return a+b-a*b;
}
inline DD split(DD a,DD b){
    if(fabs(1.0-b)==0) return 0;
    return (a-b)/(1.0-b);
}
DD f[N],g[N],p[N];
int head[N];
struct edge{
    int next,to;
    DD dis;
}E[N<<1];
inline void add(int from,int to,DD dis){
    E[++En].next=head[from];
    E[En].to=to;
    E[En].dis=dis;
    head[from]=En;
}
inline void dfs1(int u,int fa){
    f[u]=p[u];
    for(int i=head[u];i;i=E[i].next){
        int v=E[i].to;
        if(v==fa) continue;
        dfs1(v,u);
        f[u]=unit(f[u],f[v]*E[i].dis);
    }
}
inline void dfs2(int u,int fa){
    for(int i=head[u];i;i=E[i].next){
        int v=E[i].to;
        if(v==fa) continue;
        g[v]=unit(f[v],split(g[u],f[v]*E[i].dis)*E[i].dis);
        dfs2(v,u);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n-1;++i){
        int u=0,v=0,w=0;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,(DD)w/100);
        add(v,u,(DD)w/100);
    }
    for(int i=1;i<=n;++i){
        int x=0;
        scanf("%d",&x);
        p[i]=(DD)x/100;
    }
    dfs1(1,1);
    g[1]=f[1];
    dfs2(1,1);
    for(int i=1;i<=n;++i) ans+=g[i];
    printf("%.6lf\n",ans);
    return 0;
}

【題解】 P4284 [SHOI2014]概率充電器