题目链接https://nanti.jisuanke.com/t/41392
题意
给出一段程序,从根节点出发,每扫描到一个节点,如果有k个子节点,就对子节点做k次随机访问。问其中一个最深节点被访问到的概率是多少。
题解
d p [ u ] dp[u] dp[u]代表 u u u这个节点的答案, t m p tmp tmp记录只搜一次能搜到最深节点的概率。那么以 u u u为节点,一次都没搜到的概率就是 ( 1 − t m p ) k (1-tmp)^k (1−tmp)k( k k k是 u u u的子节点个数)。 d p [ u ] 就 是 1 − ( 1 − t m p ) k dp[u]就是1-(1-tmp)^k dp[u]就是1−(1−tmp)k
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e6+7;
const ll mod=1e9+7;
ll du[N];
ll dp[N];
struct Edge{
ll v,nxt;
}e[N];
ll p[N],edn;
void add(ll u,ll v){
e[++edn]=(Edge){v,p[u]};p[u]=edn;
e[++edn]=(Edge){u,p[v]};p[v]=edn;
}
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;b>>=1;
}
return res;
}
ll dg[N];
ll mx;
void dfs(ll u,ll f,ll d){
dg[u]=d;
mx=max(d,mx);
for(ll i=p[u];~i;i=e[i].nxt){
ll v=e[i].v;
if(v==f) continue;
dfs(v,u,d+1);
}
}
void solve(ll u,ll f){
if(dp[u]!=-1) return;
ll tmp=0;
for(ll i=p[u];~i;i=e[i].nxt){
ll v=e[i].v;
if(v==f) continue;
solve(v,u);
tmp=(tmp+dp[v]*qpow(du[u]-1,mod-2)%mod)%mod;
}
dp[u]=(1-qpow((1-tmp+mod)%mod,du[u]-1)+mod)%mod;
return;
}
int main() {
ll n;
scanf("%lld",&n);
for(ll i=1;i<=n;i++) p[i]=-1;edn=-1;
bool flag=true;
for(ll i=1,u,v;i<n;i++){
scanf("%lld%lld",&u,&v);
add(u,v);
du[v]++;du[u]++;
}
if(n==1){
printf("1\n");
return 0;
}
du[1]++;
dp[1]=-1;
dfs(1,0,1);
for(int i=2;i<=n;i++){
if(du[i]==1){
if(dg[i]==mx) dp[i]=1;
else dp[i]=0;
}
else dp[i]=-1;
}
solve(1,0);
printf("%lld\n",dp[1]);
}