ICPC徐州網絡賽——J. Random Access Iterator

大致題意:某個人寫了一個dfs的函數,這個函數的作用是去找一棵樹的高度,但是這個函數中 每次去找子節點的時候都是等概率隨機的選擇一個節點進行訪問,求無法正確得到樹的高度的概率。當我看到這道題的時候就覺得這道題是個簡單題,比賽的時候想的就是從底往上遞推就行了,但很可惜,我dp學得太垃圾了,而且比賽的後半段已經沒有很好的狀態去思考這道題了,賽後再看覺得這道題是真的簡單。。。。。有點坑的地方是這裏給的邊不一定是從父節點指向子節點,只是父節點和子節點的連邊(連邊順序無法直接看出父子關係)。

思路:定義dp狀態爲每一個節點不能走到最深的節點的概率,初始狀態,最深的葉子節點爲1,不是最深的葉子節點爲0。

狀態方程:u爲父節點,cnt爲子節點的個數,v爲子節點。

 

dp[u]=(\Sigma dp[v]*\frac{1}{cnt})^{cnt}

最後,代碼:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+100;
int head[maxn];
int fa[maxn];
int maxdep;
long long int dp[maxn];
int cur;
long long int quick_pow(long long int n,long long int base)
{
    long long int ans=1;
    while(n)
    {
        if(n&1)
        {
            ans*=base;
            ans%=mod;
        }
        n>>=1;
        base*=base;
        base%=mod;
    }
    return ans;
}
struct node
{
    int v,next;
}arr[maxn*2];
void add(int u,int v)
{
    arr[cur].next=head[u];
    arr[cur].v=v;
    head[u]=cur++;
}
void dep(int u,int f)
{
    maxdep=max(maxdep,f);
    for(int i=head[u];i!=-1;i=arr[i].next)
    {
        if(arr[i].v==fa[u])
            continue;
        fa[arr[i].v]=u;
        dep(arr[i].v,f+1);
    }
}
void dfs(int u,int f)
{
    int cnt=0;
    for(int i=head[u];i!=-1;i=arr[i].next)
    {
        if(arr[i].v==fa[u])
            continue;
        ++cnt;
        dfs(arr[i].v,f+1);
    }
    if(cnt==0)
    {
        if(f==maxdep)
            dp[u]=0;
        else
            dp[u]=1;
    }
    else
    {
        for(int i=head[u];i!=-1;i=arr[i].next)
        {
            dp[u]=(dp[u]+dp[arr[i].v]*quick_pow(mod-2,cnt)%mod)%mod;
        }
        dp[u]=quick_pow(cnt,dp[u]);
    }
}
int  main()
{
    int n;
    int u,v;
    cin>>n;
    memset(head,-1,sizeof head);
    for(int i=1;i<n;++i)
    {
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    dep(1,1);
    dfs(1,1);
    cout<<(1-dp[1]+mod)%mod<<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章