Random Access Iterator
题意
给一颗树,从 1 1 1号树根出发,如上述伪代码行动,问走到最深的叶子节点的概率。
思路
定义
p
b
y
[
i
]
:
i
pby[i]:i
pby[i]:i号节点走到最深的叶子概率
p
b
y
[
i
]
=
1
−
(
∑
j
∈
s
o
n
(
i
)
(
1
c
n
t
S
o
n
[
i
]
∗
(
1
−
p
b
y
[
j
]
)
)
)
c
n
t
S
o
n
[
i
]
pby[i]=1-(\sum_{j∈son(i)} (\frac{1}{cntSon[i]}*(1-pby[j])))^{cntSon[i]}
pby[i]=1−(j∈son(i)∑(cntSon[i]1∗(1−pby[j])))cntSon[i]
然后前序遍历得到深度
p
b
y
[
i
]
=
=
1
(
i
∈
叶
子
∩
d
e
[
i
]
=
=
m
a
x
d
e
p
t
h
)
pby[i]==1(i∈叶子∩de[i]==maxdepth)
pby[i]==1(i∈叶子∩de[i]==maxdepth)
p
b
y
[
i
]
=
=
0
(
i
∈
叶
子
∩
d
e
[
i
]
!
=
m
a
x
d
e
p
t
h
)
pby[i]==0(i∈叶子∩de[i]!=maxdepth)
pby[i]==0(i∈叶子∩de[i]!=maxdepth)
然后后续遍历得到所有
p
b
y
[
i
]
pby[i]
pby[i]
p
b
y
[
1
]
pby[1]
pby[1]就是答案
/* Author : Rshs
* Data : 2019-09-19-15.19
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MX = 1e6+5;
vector<int> g[MX];
int de[MX];
LL pby[MX];
int mxde;
LL quickPow(LL x,LL y,LL Mo){ //a^(mo-2) 为a的逆元
LL re=1,jin=x;
while(y){
if(y%2==1) re=re*jin%Mo;
y=y>>1;jin=jin*jin%Mo;
}
return re;
}
void gogo(int now,int pre){
for(auto v:g[now]){
if(v==pre)continue;
de[v]=de[now]+1;
mxde=max(mxde,de[v]);
gogo(v,now);
}
}
void dfs(int now,int pre){
int sz=0;
for(auto v:g[now]){
if(v==pre)continue;
dfs(v,now);
sz++;
}
if(sz==0)return ;
LL iv=quickPow(sz,mod-2,mod);
LL su=0;
for(auto v:g[now]){
if(v==pre)continue;
su=(su+(1LL-pby[v])*iv%mod)%mod;
}
su+=mod;su%=mod;
su=quickPow(su,sz,mod);
pby[now]=(1LL-su+mod)%mod;
}
int main(){
int n;cin>>n;
for(int i=1;i<n;i++){
int sa,sb;scanf("%d %d",&sa,&sb);
g[sa].push_back(sb);g[sb].push_back(sa);
}
de[1]=1;mxde=1;
gogo(1,-1);
for(int i=1;i<=n;i++)if(de[i]==mxde) pby[i]=1;
dfs(1,-1);
cout<<pby[1]<<'\n';
return 0;
}