具体而言,以下两种 dp 方式的时间复杂度究竟是什么?
约定:记 g(u,1/0) 表示 u 子树内包含/不包含 u 的最大权独立集的点权和
设 f(u,c0,c1) 表示给 u 子树内的点赋点权,使得 g(u,0)=c0 且 g(u,1)=c1 的方案数。
转移时,c0,c1 枚举范围是 [0,k⋅sz(u)]。(我认为改变这个枚举范围会影响时间复杂度,而特判 0 只影响常数)
for(int c0 = 0; c0 <= m * sz[u]; c0++) {
for(int c1 = 0; c1 <= m * sz[u]; c1++) {
if(f[u][c0][c1] == 0) continue; // 影响常数
for(int i = 0; i <= sz[v] * m; i++) {
for(int j = 0; j <= sz[v] * m; j++) {
if(f[v][i][j] == 0) continue; // 影响常数
(nf[c0 + max(i, j)][c1 + i] += f[u][c0][c1] * f[v][i][j]) %= MOD;
}
}
}
}
设 f(u,i,j) 表示给 u 子树内的点赋点权,使得 g(u,0)=i 且 max(g(u,0),g(u,1))=i+j 的方案数。
void dfs(int u, int fa) {
sz[u] = 1;
for(int i = 1; i <= m; i++) f[u][0][i] = 1;
for(int v: G[u]) {
if(v == fa) continue;
dfs(v, u), sz[u] += sz[v];
VVI nf(n * m + 1, VI(m + 1));
for(int c = 0; c <= m * sz[u]; c++) {
for(int i = 0; i <= m; i++) {
if(f[u][c][i] == 0) continue;
for(int d = 0; d <= sz[v] * m; d++) {
for(int j = 0; j <= m; j++) {
if(f[v][d][j] == 0) continue;
(nf[c + d + j][max(c + d + j, c + i + d) - (c + d + j)] += f[u][c][i] * f[v][d][j]) %= MOD;
}
}
}
}
f[u].swap(nf);
}
}
显然,第一种方法的状态数是 O(n3k2),第二种方法的状态数是 O(n2k2),但如何分析时间复杂度呢?