大致题意:某个人写了一个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;
}