有一天,小吨向火山哥请教了点分治的写法。火山哥教了小吨如下的点分治算法:
- 初始时当前连通块是整棵树。
- 首先,在当前连通块中找到任意一个点
作为该次的分治中心(不必是重心)。 - 其次,把点
在当前连通块中删去,可以得到若干个连通块。对于每个连通块再递归进行这样的操作。
不难发现,小吨从黑心火山哥那里学到的点分治在最坏情况下递归层数可以达到
%7D)
层。现在,好奇的小吨想要知道,对于一棵给定的包含

个节点的树,他有多少种不同的点分治方案呢?因为答案可能很大,你只需要输出它对

取模的值即可。
两种点分治方案不同当且仅当某一个连通块所选的点分治中心不同。
为了避免因为大家所学算法的具体细节不同出现歧义,我们还提供了一份暴力代码来具体描述这个算法。
const int mod=1e9+7;
const int maxn=5005;
bool vis[maxn];
vector<int> e[maxn];
int n;
inline void view_all(vector<int> &cur,int x,int fa){
cur.push_back(x);
for(int p: e[x]){
if (vis[p]) continue;
if (p == fa) continue;
view_all(cur, p, x);
}
}
inline int calc(int x){
vector<int> cur;
int ans = 0;
view_all(cur, x, -1);
for(int w: cur){
int res = 1;
vis[w] = 1;
for(int p: e[w]){
if (vis[p]) continue;
res = 1ll * res * calc(p) % mod;
}
vis[w] = 0;
ans = (ans + res) % mod;
}
return ans;
}
inline int get_ans(){
return calc(1);
}