如何分析此问题的时间复杂度?
查看原帖
如何分析此问题的时间复杂度?
470769
DengStar楼主2025/2/5 17:24

具体而言,以下两种 dp 方式的时间复杂度究竟是什么?
约定:记 g(u,1/0)g(u, 1/0) 表示 uu 子树内包含/不包含 uu 的最大权独立集的点权和

  1. f(u,c0,c1)f(u, c0, c1) 表示给 uu 子树内的点赋点权,使得 g(u,0)=c0g(u, 0) = c0g(u,1)=c1g(u, 1) = c1 的方案数。
    转移时,c0,c1c0, c1 枚举范围是 [0,ksz(u)][0, k\cdot sz(u)]。(我认为改变这个枚举范围会影响时间复杂度,而特判 00 只影响常数)

    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;
               }
           }
       }
     }
    
  2. f(u,i,j)f(u, i, j) 表示给 uu 子树内的点赋点权,使得 g(u,0)=ig(u, 0) = imax(g(u,0),g(u,1))=i+j\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(n^{3}k^{2}),第二种方法的状态数是 O(n2k2)O(n^{2}k^{2}),但如何分析时间复杂度呢?

2025/2/5 17:24
加载中...