2019徐州网络赛 Random Access Iterator (概率dp)

设计dp状态为f[i]表示以i为根的子树能到达正确答案的概率是多少,那么f[1]就是答案

当我们先行计算出他儿子的答案时,根据独立性以及反方向考虑,我们只需要知道一次不能到达正确答案的概率,之后重复size遍,用1去减就是答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int inf=0x3f3f3f3f;
const int N=2e6+10;
const int mod=1e9+7;
int h[N],ne[N],e[N],idx;
int depth[N];
int sign[N];
int f[N],sz[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
ll qmi(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1){
            res=res*a%mod;
        }
        b>>=1;
        a=a*a%mod;
    }
    return res;
}
void dfs(int u,int sum,int fa){
    int i;
    sign[u]=sum;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        sz[u]++;
        dfs(j,sum+1,u);
        sign[u]=max(sign[u],sign[j]);
    }
}
void dfs1(int u,int fa){
    int i;
    ll sum=0;
    for(i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        if(j==fa)
            continue;
        if(sign[j]==sign[1]){
            dfs1(j,u);
            sum=(sum+f[j])%mod;
        }
    }
    if(sz[u]==0){
        f[u]=1;
        return ;
    }
    else{
        ll cnt=(1-sum*qmi(sz[u],mod-2)+mod)%mod;
        f[u]=(1-qmi(cnt,sz[u])+mod)%mod;
        return ;
    }
}
int main(){
    ios::sync_with_stdio(false);
    memset(h,-1,sizeof h);
    int i;
    int n;
    cin>>n;
    for(i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    dfs(1,1,-1);
    dfs1(1,-1);
    cout<<f[1]<<endl;
    return 0;
}
View Code

 

posted @ 2020-08-17 09:53  朝暮不思  阅读(131)  评论(0编辑  收藏  举报