$g[i][j][k+l]+=g[i-1][j][k]*f[son[i]][l]$

#include<bits/stdc++.h>
#define fo(i, a, b) for (Re int i = (a); i <= (b); ++i)
#define fd(i, a, b) for (Re int i = (a); i >= (b); --i)
#define edge(i, u) for (Re int i = head[u], v = e[i].v; i; i = e[i].nxt, v = e[i].v)
#define N 205
#define Re register
#define pb push_back
#define F first
#define S second
#define ll long long
#define inf 1000000007
#define mp std::make_pair
#define lowbit(x) (x & -x)
#define ls (k << 1)
#define rs (k << 1 | 1)
#define mod 10007
int n, T, head[N], tot, u, v;
struct edge{
int nxt, v;
}e[N << 1];
int f[N][N], g[N][N][N];//f[i][j] 表示 i 点为根的有 j 个节点的联通块有多少点，g[i][j][k] 表示根的第 i 个儿子，最大的儿子有不超过 j 个节点，共 k 个节点的方案数，最后的时候用补集转换一下就能得到最大儿子有 j 个节点的方案数。
inline void addedge (int u, int v)
{
}
int sz[N], max[N];
inline void dfs (int u, int fa)
{
sz[u] = 1;
edge (i, u)
{
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
max[u] = std::max(max[u], sz[v]);
}
max[u] = std::max(n - sz[u], max[u]);
}
int rt1, rt2, rt, mn, ans;
inline void findroot ()
{
mn = inf;
fo (i, 1, n) mn = std::min(mn, max[i]);
rt1 = rt2 = rt = 0;
fo (i, 1, n)
if (mn == max[i])
{
if (!rt1)
rt1 = i;
else
rt2 = i;
}
if (!rt2)
{
rt = rt1;
ans = 1;//重心单独一个联通块
}
else
{
rt = ++n;//建立虚根？（其实就是让重心为 1 个）
edge (i, rt1)
if (v == rt2)
{
e[i].v = rt;
break;
}
edge (i, rt2)
if (v == rt1)
{
e[i].v = rt;
break;
}
}
}
int h[N];
inline void treedp (int u, int fa)
{
sz[u] = 1;//记得重新计算 u 点 sz 喵
f[u][0] = f[u][1] = 1;
edge (qwq, u)
{
if (v == fa) continue;
treedp(v, u);
memset(h, 0, sizeof h);
fo (i, 1, sz[u])
fo (j, 1, sz[v])
h[i + j] = (h[i + j] + f[u][i] * f[v][j]) % mod;
sz[u] += sz[v];
fo (i, 1, sz[u]) f[u][i] = (f[u][i] + h[i]) % mod;
}
}
int son[N], cnt, sum;
inline void init ()
{
ans = 0;
memset(f, 0, sizeof f);
memset(g, 0, sizeof g);
memset(max, 0, sizeof max);
tot = 0;
cnt = 0;
}
inline bool cmp (int x, int y)
{
return sz[x] < sz[y];
}
int main()
{
scanf("%d", &T);
fo (QvQ, 1, T)
{
scanf("%d", &n);
init();
fo (i, 2, n)
{
scanf("%d %d", &u, &v);
}
dfs(1, 0);
findroot();
treedp(rt, 0);
edge (i, rt)
son[++cnt] = v;
std::sort(son + 1, son + cnt + 1, cmp);
sum = 0;
fo (i, 0, 200) g[0][i][0] = g[0][i][1] = 1;
fo (i, 1, cnt)
{
fo (j, 1, sz[son[i]])
fo (k, 0, sum)
fo (l, 0, j)
{
g[i][j][k + l] = (g[i][j][k + l] + g[i - 1][std::min(j, sz[son[i - 1]])][k] * f[son[i]][l]) % mod;
}
sum += sz[son[i]];
}
fo (i, 1, sz[son[cnt]])
fo (j, i << 1, n)
ans = (ans + g[cnt][i][j] - g[cnt][i - 1][j]) % mod;
printf("Case %d: %d\n", QvQ, (ans + mod) % mod);
}
return 0;
}


(讲真我觉得我的思路到 g 函数那里都是靠 Bill Yang 学长的 blog 的自己姿势水平太低了 QAQ)