Random Access Iterator 2019 ICPC 徐州网络赛(树上概率DP)

比赛时认为给了根节点输入的点就是根和儿子的顺序了,其实输入是个无向的树,智障了,一直wa,还以为算概率写法错了。一个dfs求深度,一个dfs求dp值就可以了,简单题

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+5;
vector<int>G[N];
const ll p=1e9+7;
int n;
int depth[N];
ll dp[N];
int res=0;
ll quick_pow(ll a, ll b, ll mod)
{
    ll  r = 1, base = a;
    while (b)
    {
        if (b & 1)
            r = (r*base)% mod;
        base = (base*base) % mod;
        b >>= 1;
    }
    return r;
}
void dfs(int u,int d,int fa){
    depth[u]=d;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa)continue;
        dfs(v,d+1,u);
    }
    res=max(res,d);
}
void gao(){
    for(int i=1;i<=n;i++){
        if(depth[i]==res){
            dp[i]=1;
        }
    }
}
ll dfs2(int u,int fa){
    if(dp[u]>0)return dp[u]%p;
    ll temp=0;
    int s=G[u].size()-1;
    if(u==1)s++;
    //cout<<u<<" "<<fa<<"  "<<s<<endl;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa)continue;
        temp=(temp+quick_pow(s,p-2,p)*dfs2(v,u)%p)%p;
    }
    dp[u]=(1-quick_pow((1-temp+p)%p,s,p)+p)%p;
    return dp[u];
}
int main()
{
    scanf("%d",&n);
    int u,v;
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0,-1);
    gao();
    printf("%lld\n",dfs2(1,-1));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gzr2018/p/11494330.html