题意
将一颗(n(1 leq n leq 2000))个结点的树,分成(t(1leq t leq n))个连通块,且每个连通块的大小都小于或者等于(k(1 leq k leq 2000)),求划分方案数?
题解
(dp[i][j]):以(i)为根的子树向父亲结点(u)提供(j)个点的贡献
[dp[fa[i]][cnt_1 + cnt_2]=sum{dp[fa[i]][cnt_1] * dp[i][cnt_2]}
]
复杂度(O(nk))
代码
const int N = 2005;
const int mod = 998244353;
int n, k;
int dp[N][N], sz[N], temp[N];
vector<int> G[N];
void addedge(int u, int v) {
G[u].pb(v);
G[v].pb(u);
}
#define debug(x) cout << "____" << x << "____" << endl
void DFS(int u, int p) {
dp[u][1] = sz[u] = 1;
for (auto v : G[u]) if (v != p) {
DFS(v, u);
mem(temp, 0);
Rep(i, 1, sz[u]) Rep(j, 0, min(k - i, sz[v])) temp[i + j] = (temp[i + j] + 1ll * dp[u][i] * dp[v][j] % mod) % mod;
memcpy(dp[u], temp, sizeof(temp));
sz[u] += sz[v];
}
Rep (i, 1, k) dp[u][0] = (dp[u][0] + dp[u][i]) % mod;
}
int main()
{
cin >> n >> k;
rep (i, 1, n) {
int u, v;
cin >> u >> v;
addedge(u, v);
}
DFS(1, 0);
int ans = 0;
Rep (i, 1, k) ans = (ans + dp[1][i]) % mod;
pr(ans);
return 0;
}