首先找出原树的重心。

考虑重心的性质,有:以其为根的重构树中,每一个子树大小都不超过 $\frac{n}{2}$,那么其为重心。

又重心有一个或者两个,可以分类讨论。

两个重心

由于这两个重心相邻,所以可以切断它们之间的连边,形成两棵树。

设:$f(i,j)$ 表示以 $i$ 为根的子树中,包含 $i$ 且有 $j$ 个节点的连通块个数,可以树形背包在 $O(n^2)$ 的时间内计算。

最后答案为 $\sum_{i=1}^{\min(sz[u],sz[v])} f(u,i) \cdot f(v,i)$,其中 $u$,$v$ 表示两个重心。

一个重心

在以该重心为根求出 $f$ 的基础上,考虑使用总方案数 $\sum_{i=1}^n f(u,i)$(其中 $u$ 为重心),减去其一个子树大小大于 $\frac{i}{2}$(或等于,因为这会创造一个新的重心)的方案数。

注意到如果一个子树大小大于等于 $\frac{i}{2}$ 那么这样的子树仅有一个,可以直接枚举。

现在我们枚举了一个子树,所以在 $f(u,i)$ 中我们要退掉其的贡献,记其为 $g(v,i)$。

那么答案就是减去:

$$
\sum_{i=1}^n \sum_{j=\lceil \frac{i}{2} \rceil}^{\min(i,sz(v))} f(v,j) \cdot g(u,i-j)
$$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3;
const int mod=10007;
int n;
vector<int> E[maxn+5];
int sz[maxn+5],mx[maxn+5];
int wg[2];
int f[maxn+5][maxn+5];
int g[maxn+5][maxn+5];
int ans;
void Dfs(int u,int fa){
sz[u]=1;
for(int v:E[u]){
if(v==fa) continue;
Dfs(v,u);
sz[u]+=sz[v];
mx[u]=max(mx[u],sz[v]);
}
mx[u]=max(mx[u],n-sz[u]);
if(mx[u]<=n/2) wg[bool(wg[0])]=u;
}
void DfsF(int u,int fa){
f[u][1]=1;
sz[u]=1;
for(int v:E[u]){
if(v==fa) continue;
DfsF(v,u);
sz[u]+=sz[v];
for(int i=sz[u];i;i--)
for(int j=1;j<=sz[v]&&j<=i;j++)
f[u][i]=(f[u][i]+f[u][i-j]*f[v][j])%mod;
}
}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
int u,v;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
E[u].push_back(v),E[v].push_back(u);
}
Dfs(1,0);
if(wg[1]){
DfsF(wg[0],wg[1]);
DfsF(wg[1],wg[0]);
for(int i=1;i<=sz[wg[0]]&&i<=sz[wg[1]];i++)
ans=(ans+f[wg[0]][i]*f[wg[1]][i])%mod;
}
else{
u=wg[0],DfsF(u,0);
for(int i=1;i<=n;i++)
ans=(ans+f[u][i])%mod;
for(int v:E[u]){
for(int i=1;i<=n;i++){
g[v][i]=f[u][i];
for(int j=1;j<=sz[v]&&j<=i;j++)
g[v][i]=(g[v][i]-g[v][i-j]*f[v][j])%mod;
for(int j=ceil(i/2.0);j<=i&&j<=sz[v];j++)
ans=(ans-g[v][i-j]*f[v][j])%mod;
}
}
}
printf("%d",(ans+mod)%mod);
return 0;
}