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