P8352 SDOI2022 D2T1 小 N 的独立集 题解
Un1quAIoid · · 题解
传送门:P8352 [SDOI/SXOI2022] 小 N 的独立集
题意
给定
1. 经典 dp
枚举所有权值分配方案,设
2. dp 套 dp
经典 dp 和极小的值域
设
套用树上背包的复杂度分析可得时间复杂度为
因为状态转移时是将内层
3. 状态优化
上文的 dp 方法复杂度瓶颈在于状态数就已经到达了
时间复杂度
代码(代码中的
//dp套dp
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1001;
const int Mod = 1e9+7;
int n, k, siz[MAXN];
int f[MAXN][MAXN * 5][6], t[MAXN * 5][6];
int head[MAXN], edge_num;
struct edge {
int nxt, to;
} T[MAXN * 2];
inline void add(int u, int v) {
T[++edge_num] = (edge) {head[u], v};
head[u] = edge_num;
}
inline void Add(int &a, int b) { a += b; if (a >= Mod) a -= Mod; }
void dfs(int x, int fa) {
siz[x] = 1;
for (int i = 1; i <= k; i++) f[x][0][i] = 1;
for (int i = head[x]; i; i = T[i].nxt) {
int son = T[i].to;
if (son == fa) continue;
dfs(son, x);
memset(t, 0, sizeof(t));
for (int i = 0; i <= k * siz[x]; i++)
for (int j = 0; j <= k; j++) if (f[x][i][j])
for (int p = 0; p <= k * siz[son]; p++)
for (int q = 0; q <= k; q++) if (f[son][p][q])
Add(t[i + p + q][max(i + j + p, i + p + q) - (i + p + q)], 1ll * f[x][i][j] * f[son][p][q] % Mod);
memcpy(f[x], t, sizeof(t));
siz[x] += siz[son];
}
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfs(1, 0);
for (int i = 1; i <= k * n; i++) {
int ans = 0;
for (int d = 0; d <= min(i, k); d++) Add(ans, f[1][i - d][d]);
printf("%d\n", ans);
}
return 0;
}