【题解】CF1499F Diameter Cuts
提供一个比较笨的 DP 方法。
记
我们来处理
接下来考虑优化。首先可以对
然后把子节点的
最后的转移方程为
需要特判叶子。
以
#include <bits/stdc++.h>
using namespace std;
template <typename T> void rd(T &x) {
x = 0;
int f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - 48;
c = getchar();
}
x *= f;
}
template <typename T, typename... T2> void rd(T &x, T2 &...y) {
rd(x), rd(y...);
}
typedef long long ll;
const int mod = 998244353;
const int N = 5010, M = N;
int n, m;
vector<int> e[N];
int f[N][M], sum[N][M], pre[M];
void dfs(int u, int fa) {
if (e[u].size() == !!fa) {
f[u][0] = sum[u][0] = f[u][1] = 1;
fill(sum[u] + 1, sum[u] + m + 2, 2);
return;
}
for (int v : e[u]) {
if (v == fa) continue;
dfs(v, u);
}
for (int t = 0; t <= 1; ++t) {
fill(pre, pre + m + 1, 1);
bool fl = false;
for (int v : e[u]) {
if (v == fa) continue;
if (t && fl) f[v][0] = 0;
for (int i = t; i <= m; ++i) {
f[v][i] = f[v][i] * (ll)pre[min(i - t, m - i)] % mod;
}
for (int i = 0; i <= m; ++i)
pre[i] = pre[i] * (ll)sum[v][i] % mod;
fl = true;
}
reverse(e[u].begin(), e[u].end());
}
for (int i = 0; i <= m; ++i) {
for (int v : e[u]) {
if (v == fa) continue;
(f[u][i + 1] += f[v][i]) %= mod;
}
(f[u][0] += f[u][i + 1]) %= mod;
}
sum[u][0] = f[u][0];
for (int i = 0; i <= m; ++i) {
(sum[u][i + 1] = sum[u][i] + f[u][i + 1]) %= mod;
}
}
int main() {
rd(n, m);
for (int i = 1; i < n; ++i) {
int u, v;
rd(u, v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1, 0);
printf("%d", sum[1][0]);
}