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。
题解
很难直接计算被充电的个数,所以反过来,
设
fi
表示不考虑父亲,不能被充电的概率。
设
gi
表示只考虑父亲,不能被充电的概率。
fi∗=fj+(1−fj)∗(1−v)
儿子不通电的概率加上儿子通电但边不同电的概率。
计算g的方式类似。
code
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 500003
#define M 503
#define db double
#define P putchar
#define G getchar
#define inf 998244353
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int lst[N],nxt[N*2],to[N*2],w[N],n,x,y,z,tot,q[N],fa[N];
bool bz[N];
db f[N],g[N],t,ans,v[N*2];
void ins(int x,int y,int z)
{
nxt[++tot]=lst[x];
to[tot]=y;
v[tot]=(db)z/100;
lst[x]=tot;
}
void bfs(int x)
{
memset(bz,1,sizeof(bz));
bz[q[1]=x]=0;
int i=0,j=1;
while(i<j)
{
x=q[++i];
for(int k=lst[x];k;k=nxt[k])
if(bz[to[k]])bz[q[++j]=to[k]]=0,fa[to[k]]=x;
}
}
int main()
{
freopen("charger.in","r",stdin);
freopen("charger.out","w",stdout);
read(n);
for(int i=1;i<n;i++)
read(x),read(y),read(z),ins(x,y,z),ins(y,x,z);
for(int i=1;i<=n;i++)
read(w[i]);
bfs(1);
g[1]=1;
for(int i=n;i;i--)
{
x=q[i];
f[x]=1-(db)w[x]/100;
for(int j=lst[x];j;j=nxt[j])
if(to[j]!=fa[x])f[x]*=f[to[j]]+(1-f[to[j]])*(1-v[j]);
}
for(int i=1;i<=n;i++)
{
x=q[i];
for(int j=lst[x];j;j=nxt[j])
if(to[j]!=fa[x])
{
t=f[to[j]]+(1-f[to[j]])*(1-v[j]);
t=t?f[x]/t*g[x]:0;
g[to[j]]=t+(1-t)*(1-v[j]);
}
}
for(int i=1;i<=n;i++)
ans+=1-f[i]*g[i];
printf("%.6lf\n",ans);
}