jzoj 3661. 【SHTSC2014】概率充電器

Description

著名的電子產品品牌SHOI剛剛發佈了引領世界潮流的下一代電子產品——概率充電器:
“採用全新納米級加工技術,實現元件與導線能否通電完全由真隨機數決定!SHOI概率充電器,您生活不可或缺的必需品!能充上電嗎?現在就試試看吧!”
SHOI概率充電器由n-1條導線連通了n個充電元件。進行充電時,每條導線是否可以導電以概率決定,每一個充電元件自身是否直接進行充電也由概率決定。隨後電能可以從直接充電的元件經過通電的導線使得其他充電元件進行間接充電。
作爲SHOI公司的忠實客戶,你無法抑制自己購買SHOI產品的衝動。在排了一個星期的長隊之後終於入手了最新型號的SHOI概率充電器。你迫不及待地將SHOI概率充電器插入電源——這時你突然想知道,進入充電狀態的元件個數的期望是多少呢?

Input

第一行一個整數:n。概率充電器的充電元件個數。充電元件由1-n編號。
之後的n-1行每行三個整數a, b, p,描述了一根導線連接了編號爲a和b的充電元件,通電概率爲p%。
第n+2行n個整數:qi。表示i號元件直接充電的概率爲qi%。

Output

輸出一行一個實數,爲能進入充電狀態的元件個數的期望,四捨五入到小數點後6位小數。

Sample Input

輸入1:
3
1 2 50
1 3 50
50 0 0
輸入2:
5
1 2 90
1 3 80
1 4 70
1 5 60
100 10 20 30 40

Sample Output

輸出1:
1.000000
輸出2:
4.300000

Data Constraint

對於30%的數據,n≤5000。
對於100%的數據,n≤500000,0≤p,qi≤100。


Sulotion

因爲一個元件通電的概率非常難算(只要周圍有一個通電且能傳輸過來就行),我們可以先算其不通電的概率(周圍每個要麼不通電,要麼通電了沒傳過來)
可以設f[i],g[i],分別表示節點i從其兒子和父親方向的不通電概率。
f[i]=(1q[i])jif[j]+(1f[j])(1Wij)
T=f[fa[i]]g[fa[i]]f[i]+(1f[i])(1Wfa[i]i) ( 表示其父親不由自己推出的不通電概率)
g[i]=T+(1T)(1Wifa[i])

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;

#define DB double
#define N 500500

struct note
{
    int x,y,next;
    DB w;
};

note side[N*2];
DB f[N],g[N],q[N],t,ans;
int last[N],df[N],tt[N],n,l,tot;

void add(int x,int y,DB w)
{
    l++; side[l].x=x; side[l].y=y; side[l].w=w;
    side[l].next=last[x]; last[x]=l;
}

void init()
{
    scanf("%d",&n);
    int x,y;
    DB z;
    for (int i=1;i<n;i++)
    {
        scanf("%d%d%lf",&x,&y,&z);
        add(x,y,z/100.0);
        add(y,x,z/100.0);
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%lf",&q[i]);
        q[i]/=100.0;
    }
}

queue<int> Q;
void bfs()
{
    memset(tt,0,sizeof(tt));
    tt[1]=1; Q.push(1);
    while (!Q.empty())
    {
        int x=Q.front(); Q.pop();
        for (int i=last[x];i!=0;i=side[i].next)
        {
            int j=side[i].y;
            if (tt[j]==1) continue;
            df[++tot]=i;
            Q.push(j); tt[j]=1;
        }   
    }
}

void bfs1()
{
    for (int i=1;i<=n;i++)
        f[i]=1.0-q[i];
    for (int i=n-1;i>=1;i--)
    {
        int x=side[df[i]].x;
        int y=side[df[i]].y;
        DB w=side[df[i]].w;
        f[x]*=(f[y]+(1.0-f[y])*(1.0-w));
    }
//  for (int i=1;i<=n;i++)
//      printf("%d %lf\n",i,f[i]);
}

void bfs2()
{
    g[1]=1.0;
    for (int i=1;i<=n-1;i++)
    {
        int num=df[i];
        int fa=side[num].x,x=side[num].y; 
        t=f[fa]*g[fa]/(f[x]+(1.0-f[x])*(1.0-side[num].w));
        g[x]=t+(1.0-t)*(1.0-side[num].w);
    }
    //for (int i=1;i<=n;i++)
    //  printf("%d %lf\n",i,g[i]);
    for (int i=1;i<=n;i++)
        ans+=(1.0-f[i]*g[i]);
}

int main()
{
    freopen("charger.in","r",stdin);
    freopen("charger.out","w",stdout);
    init();
    bfs();
    bfs1();
    bfs2();
    printf("%.6lf\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章