19 icpc徐州网络赛 Random Access Iterator //树上概率dp

13 篇文章 0 订阅
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(json(i)(cntSon[i]1(1pby[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(ide[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(ide[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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值