題意:
給你一棵以1爲根的樹,以如下方式遍歷這個樹來求樹的高度(根節點與葉子節點之間的最大距離)
從根節點出發,隨機遍歷每個子樹,問能夠計算出樹的高度的概率是多少,
要求結果對1000000007取模(,其中a爲分子,b爲分母)
分析:
樹形DP與概率相結合,和之前南京網絡賽的題目方向相似
dp[i]:表示第i個節點爲根來能夠求出當前子樹的概率爲多少
注意到:
對於葉子節點且不是與根節點距離最大的葉子節點(如下圖中的2),dp值爲0
對於與根節點距離最大葉子節點(如下圖中的3、4),dp值爲1
我們考慮dp方程的轉移,以1節點爲例子
我們考慮無法求出爭取高度的概率爲P,那麼求出正確高度的概率爲1 - P
對於1節點我們有三次選擇方式,每次等概率選擇所有的點,那麼有以下幾種排列方式
排列方式 | 概率 |
---|---|
對右邊式子求和整理,得
又因爲每種情況的概率相同我們可以得到
依次類推我們得到dp的狀態轉移
其中對於取模問題,我們每次都將算出來的分數用逆元的方式化爲整數即可
代碼:
/*************************************************************************
> File Name: 2019_Xuzhou_J.cpp
> Author: z472421519
> Mail:
> Created Time: 2019年09月07日 星期六 15時39分03秒
************************************************************************/
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#define MAXN 1000003
#define ll long long
const ll mod = 1e9 + 7;
using namespace std;
//double AXN],ans;
int dep[MAXN],son[MAXN],g[MAXN],edgesize,res;
struct edges{
int f,t;
void var(int a,int b)
{
f = a;
t = b;
}
}edges[MAXN * 2];
void addedge(int f,int t)
{
edges[++edgesize].var(g[f],t);
g[f] = edgesize;
}
void dfs(int now,int d)
{
res = max(d,res);
dep[now] = d;
son[now] = 0;
for(int i = g[now];i != -1;i = edges[i].f)
{
if(dep[edges[i].t])
continue;
son[now]++;
dfs(edges[i].t,d + 1);
}
}
/*
struct node
{
int a,b;
};*/
ll quick_pow(ll a,ll n)
{
ll res = 1;
while(n)
{
if(n & 1)
res = (res * a) % mod;
a = (a * a) % mod;
n >>= 1;
}
return res;
}
ll inv(ll a)
{
return quick_pow(a,mod - 2);
}
ll dfs_dp(int now)
{
//printf("%d %lf\n",now,dp[now]);
if(dep[now] == res)
{
return 1;
}
if(son[now] == 0)
return 0;
/*
node t,T;
t.a = 0;
t.b = 0;
*/
ll t = 0,T = 0;
for(int i = g[now];i != -1;i = edges[i].f)
{
if(dep[edges[i].t] < dep[now])
continue;
//if(t.b == 0)
//dp[edges[i].t] = dp[now] * (2.0 * son[now] - 1) / (son[now] * son[now]);
T = dfs_dp(edges[i].t);
T = (1 - T + mod) % mod;
t = (t + T) % mod;
}
t = quick_pow(t,son[now]);
ll res = quick_pow(inv(son[now]),son[now]);
t = t * res % mod;
res = (1 - t + mod) % mod;
//printf("%d %lld\n",now,res);
return res;
}
int main()
{
int n;
//printf("%lld %lld\n",(1 - 3 * inv(4) + mod) % mod,1 * inv(4) % mod);
scanf("%d",&n);
res = 0;
memset(g,-1,sizeof(g));
for(int i = 1;i < n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(1,1);
//printf("%d\n",res);
//node t;
ll t = dfs_dp(1);
printf("%lld\n",t);
return 0;
}