题目大意
著名的电子产品品牌SHOI刚刚发布了引领世界潮流的下一代电子产品——概率充电器:
“采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧!”
SHOI概率充电器由n-1条导线连通了n个充电元件。进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定。随后电能可以从直接充电的元件经过通电的导线使得其他充电元件进行间接充电。
作为SHOI公司的忠实客户,你无法抑制自己购买SHOI产品的冲动。在排了一个星期的长队之后终于入手了最新型号的SHOI概率充电器。你迫不及待地将SHOI概率充电器插入电源——这时你突然想知道,进入充电状态的元件个数的期望是多少呢?
解题思路
考虑计算充电的期望很复杂,考虑分别计算以1为根,从上到下,从下到上充不上电的概率。先计算从下到上,再计算从上到下即可。考虑到会爆栈,用bfs即可。
code
using namespace std;
int const mn=5*1e5+9,mm=1e6+9,inf=1e9+7;
int n,gra,begin[mn],to[mm],next[mm],q[mn],inq[mn];
LF f[mn],g[mn],len[mm],a[mn];
void insert(int u,int v,LF w){
to[++gra]=v;
len[gra]=w;
next[gra]=begin[u];
begin[u]=gra;
}
int main(){
//freopen("charger.in","r",stdin);
//freopen("charger.out","w",stdout);
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d",&n);
fo(i,1,n-1){
int a,b;LF p;
scanf("%d%d%lf",&a,&b,&p),p/=100;
insert(a,b,p);
insert(b,a,p);
}
fo(i,1,n)scanf("%lf",&a[i]),a[i]/=100;
int ti=0;
inq[q[++ti]=1]=1;
fo(i,1,n){
int now=q[i];
fr(j,now)if(!inq[to[j]])inq[q[++ti]=to[j]]=1;
}
fo(i,1,n)inq[i]=0;
fd(i,n,1){
int now=q[i];inq[now]=1;
f[now]=1-a[now];
fr(j,now)if(inq[to[j]]){
f[now]*=1-len[j]*(1-f[to[j]]);
}
}
g[1]=1;
fo(i,1,n)inq[i]=0;
fo(i,1,n){
int now=q[i];inq[now]=1;
fr(j,now)if(!inq[to[j]]){
if(1-len[j]*(1-f[to[j]]))g[to[j]]=1-len[j]*(1-f[now]*g[now]/(1-len[j]*(1-f[to[j]])));
else g[to[j]]=1-len[j];
}
}
LF ans=0;
fo(i,1,n)ans+=1-f[i]*g[i];
printf("%.6lf",ans);
return 0;
}