题目:
https://ac.nowcoder.com/acm/problem/20589
有 n − 1 n-1 n−1个导线联通 n n n个充电元件,每个充电元件有 a i a_i ai概率直接进入充电状态,每个导线有 b i b_i bi概率导电,而且每个进入充电状态的元件可以通过导电的导线使其他元件进入充电状态。求进入充电状态的元件个数的期望是多少?
思路:
首先题目中给出的一个点被充电的条件是自己有电或周边点有电且连接的边导电,如果直接计算要用容斥。但是我们可以计算一个点不充电的概率,那么就是自己不直接进入充电状态且周围的点不会有电传给该点,因为周围不会有电传给该点的事件都是独立的,可以直接用乘法原理。
设
p
(
u
)
p(u)
p(u)表示点
u
u
u不充电的概率,
e
(
u
,
v
)
e(u,v)
e(u,v)表示
(
u
,
v
)
(u,v)
(u,v)边导电的概率,则有
p
(
u
)
=
(
1
−
a
u
)
∏
(
u
,
v
)
∈
E
[
1
−
e
(
u
,
v
)
+
e
(
u
,
v
)
p
(
v
)
]
p(u)=(1-a_u)\prod_{(u,v)\in E}[1-e(u,v)+e(u,v)p(v)]
p(u)=(1−au)(u,v)∈E∏[1−e(u,v)+e(u,v)p(v)]
解释就是首先它自己不能亮,然后枚举所有相邻的点,如果边不能导电那就没问题,如果边导电了相邻点就不能导电。
设
f
(
u
)
f(u)
f(u)表示是
u
u
u不被它儿子(含自身)导电的概率。则上面那个式子相当于对每个点
u
u
u,以
u
u
u为根按照下面式子
d
p
dp
dp
f
(
u
)
=
(
1
−
a
u
)
∏
v
∈
s
o
n
(
u
)
[
1
−
e
(
u
,
v
)
+
e
(
u
,
v
)
f
(
v
)
]
f(u)=(1-a_u)\prod_{v\in son(u)}[1-e(u,v)+e(u,v)f(v)]
f(u)=(1−au)v∈son(u)∏[1−e(u,v)+e(u,v)f(v)]
p
(
u
)
=
f
(
u
)
p(u)=f(u)
p(u)=f(u),因为对于根来说,周围所有的点不传电过来就是所有的儿子节点不传电过来。但是时间复杂度太高,考虑换根
d
p
dp
dp。
先随便确定一个根,把无根树变成有根树
G
r
o
o
t
G_{root}
Groot进行一次上面式子的
d
p
dp
dp,求出所有的
f
f
f函数值,
f
(
u
)
f(u)
f(u)表示在
G
r
o
o
t
G_{root}
Groot下
d
p
dp
dp得到的函数值,
p
(
u
)
p(u)
p(u)表示以
u
u
u为根
d
p
dp
dp得到的函数值。
注意: 接下来分析中点与点的关系都是在
G
r
o
o
t
G_{root}
Groot下(结合图)。
对于不是根的点
u
u
u,如果要以点
u
u
u为根
d
p
dp
dp,则
p
(
u
)
=
f
′
(
u
)
=
(
1
−
a
u
)
∏
v
∈
s
o
n
(
u
)
∪
{
f
a
}
[
1
−
e
(
u
,
v
)
+
e
(
u
,
v
)
f
′
(
v
)
]
=
(
1
−
a
u
)
∏
v
∈
s
o
n
(
u
)
[
1
−
e
(
u
,
v
)
+
e
(
u
,
v
)
f
(
v
)
]
+
1
−
e
(
u
,
f
a
)
+
e
(
u
,
f
a
)
f
′
(
f
a
)
=
f
(
u
)
+
1
−
e
(
u
,
f
a
)
+
e
(
u
,
f
a
)
f
′
(
f
a
)
\begin{aligned} p(u)&=f^{'}(u)=(1-a_u)\prod_{v\in son(u)\cup \{fa\}}[1-e(u,v)+e(u,v)f^{'}(v)]\\ &=(1-a_u)\prod_{v\in son(u)}[1-e(u,v)+e(u,v)f(v)]+1-e(u,fa)+e(u,fa)f^{'}(fa)\\ &=f(u)+1-e(u,fa)+e(u,fa)f^{'}(fa)\\ \end{aligned}
p(u)=f′(u)=(1−au)v∈son(u)∪{fa}∏[1−e(u,v)+e(u,v)f′(v)]=(1−au)v∈son(u)∏[1−e(u,v)+e(u,v)f(v)]+1−e(u,fa)+e(u,fa)f′(fa)=f(u)+1−e(u,fa)+e(u,fa)f′(fa)
f
′
f^{'}
f′表示以
u
u
u为根
d
p
dp
dp的函数值。对于在
G
r
o
o
t
G_{root}
Groot中就是点
u
u
u的儿子,在以
u
u
u为根也是,所以
f
(
v
)
=
f
′
(
v
)
f(v)=f^{'}(v)
f(v)=f′(v)。而
f
′
(
f
a
)
=
(
1
−
a
f
a
)
∏
(
f
a
,
v
)
∈
E
,
v
≠
u
[
1
−
e
(
f
a
,
v
)
+
e
(
f
a
,
v
)
f
′
(
v
)
]
=
(
1
−
a
f
a
)
∏
(
f
a
,
v
)
∈
E
,
v
≠
u
[
1
−
e
(
f
a
,
v
)
+
e
(
f
a
,
v
)
f
′
′
(
v
)
]
=
(
1
−
a
f
a
)
∏
(
f
a
,
v
)
∈
E
[
1
−
e
(
f
a
,
v
)
+
e
(
f
a
,
v
)
f
′
′
(
v
)
]
1
−
e
(
f
a
,
u
)
+
e
(
f
a
,
u
)
f
′
′
(
u
)
=
p
(
f
a
)
1
−
e
(
f
a
,
u
)
+
e
(
f
a
,
u
)
f
(
u
)
\begin{aligned} f^{'}(fa)&=(1-a_{fa})\prod_{(fa,v)\in E,v\neq u}[1-e(fa,v)+e(fa,v)f^{'}(v)]\\ &=(1-a_{fa})\prod_{(fa,v)\in E,v\neq u}[1-e(fa,v)+e(fa,v)f^{''}(v)]\\ &=\frac{(1-a_{fa})\prod_{(fa,v)\in E}[1-e(fa,v)+e(fa,v)f^{''}(v)]}{1-e(fa,u)+e(fa,u)f^{''}(u)}\\ &=\frac{p(fa)}{1-e(fa,u)+e(fa,u)f(u)}\\ \end{aligned}
f′(fa)=(1−afa)(fa,v)∈E,v=u∏[1−e(fa,v)+e(fa,v)f′(v)]=(1−afa)(fa,v)∈E,v=u∏[1−e(fa,v)+e(fa,v)f′′(v)]=1−e(fa,u)+e(fa,u)f′′(u)(1−afa)∏(fa,v)∈E[1−e(fa,v)+e(fa,v)f′′(v)]=1−e(fa,u)+e(fa,u)f(u)p(fa)
f
′
′
f{''}
f′′表示以
f
a
fa
fa为根
d
p
dp
dp的函数值,对于
v
v
v在
G
u
G_{u}
Gu时是
f
a
fa
fa的儿子,在
G
f
a
G_{fa}
Gfa时也是
f
a
fa
fa的儿子,所以
f
′
′
(
v
)
=
f
′
(
v
)
f^{''}(v)=f^{'}(v)
f′′(v)=f′(v)。
u
u
u在
G
r
o
o
t
G_{root}
Groot下是
f
a
fa
fa的儿子,在
G
f
a
G_{fa}
Gfa的时候也是,所以
f
′
′
(
u
)
=
f
(
u
)
f^{''}(u)=f(u)
f′′(u)=f(u)。由于
f
f
f函数,
p
(
r
o
o
t
)
p(root)
p(root)已经求出来了,所以只需要
D
F
S
DFS
DFS用父节点的
p
p
p值更新自己就行。
注意: 在计算
f
′
(
f
a
)
=
p
(
f
a
)
1
−
e
(
f
a
,
u
)
+
e
(
f
a
,
u
)
f
(
u
)
f^{'}(fa)=\frac{p(fa)}{1-e(fa,u)+e(fa,u)f(u)}
f′(fa)=1−e(fa,u)+e(fa,u)f(u)p(fa)时,如果
1
−
e
(
f
a
,
u
)
+
e
(
f
a
,
u
)
f
(
u
)
=
0
e
(
f
a
,
u
)
[
1
−
f
(
u
)
]
=
1
\begin{aligned} 1-e(fa,u)+e(fa,u)f(u)&=0\\ e(fa,u)[1-f(u)]&=1 \end{aligned}
1−e(fa,u)+e(fa,u)f(u)e(fa,u)[1−f(u)]=0=1
因为
0
≤
e
(
f
a
,
u
)
,
f
(
u
)
≤
1
0\le e(fa,u),f(u)\le 1
0≤e(fa,u),f(u)≤1,所以只能
e
(
f
a
,
u
)
=
1
,
f
(
u
)
=
0
e(fa,u)=1,f(u)=0
e(fa,u)=1,f(u)=0。
f
(
u
)
=
0
f(u)=0
f(u)=0表明
u
u
u一定充电,所以直接令
p
(
u
)
=
0
p(u)=0
p(u)=0。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=2e6;
struct Edge
{
int v;
double w;
} e[N];
int mm,n,fst[N],nxt[N];
double p[N],f[N],g[N];
void ade(int u,int v,double w)
{
e[++mm]=(Edge)
{
v,w
};
nxt[mm]=fst[u],fst[u]=mm;
}
void dfs1(int u,int fa)
{
f[u]=1-p[u];
for(int i=fst[u]; i; i=nxt[i])
{
int v=e[i].v;
if(v==fa)
continue;
dfs1(v,u);
f[u]*=(1-e[i].w+e[i].w*f[v]);
}
}
void dfs2(int u,int fa,int ei)
{
if(u==1)
g[u]=f[u];//如果u是根,那么什么都不用管.
else
{
double tmp=1-e[ei].w+e[ei].w*f[u],P;
if(!tmp)//特判
g[u]=0;
else
{
P=g[fa]/tmp;
g[u]=f[u]*(1-e[ei].w+e[ei].w*P);
}
}
for(int i=fst[u]; i; i=nxt[i])
{
int v=e[i].v;
if(v==fa)
continue;
dfs2(v,u,i);
}
}
int main()
{
scanf("%d",&n);
for(int i=1; i<n; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
ade(u,v,w*0.01),ade(v,u,w*0.01);
}
for(int i=1; i<=n; i++)
scanf("%lf",p+i),p[i]*=0.01;
dfs1(1,0),dfs2(1,0,0);
double ans=0;
for(int i=1; i<=n; i++)
ans+=1-g[i];
printf("%.6lf",ans);
}