The Preliminary Contest for ICPC Asia Xuzhou 2019 J Random Access Iterator(树型dp)

5 篇文章 0 订阅

题目链接: https://nanti.jisuanke.com/t/41392

题目大意:

1 1 1号节点作为根节点,假如当前节点有 m m m个子节点,就进行 m m m次等概率的选择下一个节点,直到叶子节点为止,问最后走到最深的叶子节点的概率。

解题思路:

树上的一个 d p dp dp转移,直接考虑转移到合法的情况比较复杂,每次转移我们考虑转移不到合法节点的情况。
d p [ i ] dp[i] dp[i]表示 i i i号节点不能到达最深节点的概率 那么 i i i号节点能到达最深节点的概率就是 1 − d p [ i ] 1-dp[i] 1dp[i]
假设当前节点 u u u m m m个子节点,有 s s s 不 可 能 不可能 到达最深的叶子节点 v v v
那么转移到这 s s s个节点的概率就是: d p [ u ] = ( 1 − ( ∑ i = 1 s d p [ v ] m ) m ) dp[u]=(1-(\frac{\sum \limits _{i=1}^{s} dp[v]} {m})^m) dp[u]=(1(mi=1sdp[v])m)

然后就是建边的时候建双向边,树形dp一下就可以了,最后的答案就是 1 − d p [ 1 ] 1-dp[1] 1dp[1]

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define pb push_back
using namespace std;
const int mod=(int)1e9+7;
int n,m;
const int maxn=(int)1e6+5;

int dp[maxn];
vector<int>v[maxn];
int dep[maxn];
int maxx=0;
void dfs(int now,int fa, int depth)
{
    maxx=max(depth,maxx);
    dep[now]=depth;
    for(auto nxt:v[now])
    {
        if(nxt==fa)continue;
        dfs(nxt,now,depth+1);
    }
}
ll qpm(ll a,ll b,ll c)
{
    ll res=1;
    while(b)
    {
        if(b & 1)
        {
            res=(res*a)%c;
        }
        a=(a*a)%c;
        b=b>>1;
    }
    return res;
}
int inv(int x)
{
    return qpm(x,mod-2,mod);
}

void solve(int now,int fa)
{
    int sum=0;
    int num=0;
    for(auto nxt:v[now])
    {
        if(nxt==fa)continue;
        num++;
        solve(nxt,now);
        sum=(sum+dp[nxt])%mod;
    }
    if(num==0)
    {
        if(dep[now]==maxx)dp[now]=0;
        else dp[now]=1;
        return;
    }
    sum=(sum*inv(num))%mod;
    dp[now]=qpm(sum,num,mod);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    int x,y;
    for(int i=1;i<=n-1;i++)
    {
        cin>>x>>y;
        v[x].pb(y);
        v[y].pb(x);
    }
    dfs(1,0,1);
    //cout<<"!!!"<<endl;
    memset(dp,0,sizeof(dp));
    solve(1,0);
    cout<<(1-dp[1]+mod)%mod<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值