题目
这个题。。。
如果我们只考虑从儿子到父亲的传输电,之后可以再用一个dfs从上至下更新父亲对儿子的贡献。
但是这个题需要求的是概率而非期望(直接算期望不好求),就没有那些什么线性性:
P
(
A
∣
B
)
=
P
(
A
)
+
P
(
B
)
−
P
(
A
)
∗
P
(
B
)
P(A|B) = P(A) + P(B) - P(A) * P(B)
P(A∣B)=P(A)+P(B)−P(A)∗P(B)
P
(
A
)
=
P
(
A
∣
B
)
−
P
(
B
)
1
−
P
(
B
)
P(A)=\frac {P(A|B)-P(B)}{1-P(B)}
P(A)=1−P(B)P(A∣B)−P(B)
注意对于第二个式子,Claris大佬认为会除0,于是还存了当前的概率上有几个0,但其实是不需要的,如果
P
(
B
)
=
1
P(B)=1
P(B)=1,那么。。。下面是一定会通电的,直接赋值
d
p
=
1
dp=1
dp=1就行
A
C
C
o
d
e
:
{\rm AC \ Code:}
AC Code:
#include<bits/stdc++.h>
#define maxn 500005
#define double long double
using namespace std;
int n;
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
double cst[maxn<<1];
inline void Node(int u,int v,double ct){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=ct; }
double zc[maxn];
double dp[maxn];
void dfs(int now,int ff)
{
dp[now] = zc[now];
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff)
{
dfs(to[i],now);
double tmp = dp[to[i]] * cst[i];
dp[now] = dp[now] + tmp - dp[now] * tmp;
}
}
double dp2[maxn],ans;
void ser(int now,int ff)
{
ans +=dp2[now];
for(int i=info[now];i;i=Prev[i])
if(to[i]!=ff)
{
double tmp = dp[to[i]] * cst[i];
if(fabs(tmp - 1)<1e-8) dp2[to[i]] = 1;
else
{
double pfa = (dp2[now]-tmp)/(1-tmp)*cst[i];
dp2[to[i]] = dp[to[i]] + pfa - pfa * dp[to[i]];
}
ser(to[i],now);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v,p;
scanf("%d%d%d",&u,&v,&p);
Node(u,v,p/100.0),Node(v,u,p/100.0);
}
for(int i=1;i<=n;i++) scanf("%Lf",&zc[i]),zc[i]/=100;
dfs(1,0);
dp2[1] = dp[1];
ser(1,0);
printf("%.6Lf",ans);
}