首页 > 其他分享 >P8352 [SDOI/SXOI2022] 小 N 的独立集

P8352 [SDOI/SXOI2022] 小 N 的独立集

时间:2024-01-31 11:14:04浏览次数:26  
标签:SDOI SXOI2022 int max 复杂度 P8352 mathcal sum DP

还是先打暴力,枚举 \(k^n\) 种树的形态做树形 DP,时间复杂度 \(\mathcal O(nk^n)\),拿下 \(n \le 8\) 和 \(k = 1\) 的 \(25\) 分。

虽然很简单,还是交代下吧:设 \(f(u, 0/1)\) 表示以 \(u\) 为根的子树中是否选 \(u\) 的最大权独立集,\(f(u, 0) \gets w_u + \sum\limits_{v \in son_u} \max\{f(v, 0), f(v, 1)\}, f(u, 1) \gets \sum\limits_{v \in son_u} f(v, 0)\)。答案是 \(\max\{f(u, 0), f(u,1)\}\)。

把相同的 \(\mathcal O(n)\) DP 做 \(k^n\) 次很笨蛋,考虑优化这个过程,上 DP 套 DP!

设 \(F(u, i,j)\) 表示 \(f(u, 0) = i, f(u, 1) = j\) 的方案数,转移时考虑逐个加入子结点 \(v\),有:

\[F(u, i, j) \gets F(u, i, j) + \sum_{p, q \le i} F(u, i - \max\{p, q\}, j - p) \times F(v, p, q) \]

一个重要性质是 \(\max\{f(u, 0), f(u, 1) \} \in [f(u, 0), f(u, 0) + k]\),证明是显然的:\(f(u, 0) \ge f(u, 1) - w_u, w_u \in [1, k]\)。

然后状态数 \(\mathcal O(n^2k^3)\),时间复杂度 \(\mathcal O(n^4k^4)\),非常跑不满,但也不可能过,能有 \(60\) 分吧?

不合法状态很多,且转移时用到的是 \(\max\{i, j \}\),单独记个 \(j\) 显得有些浪费,考虑优化。

根据重要性质,设 \(F(u, i, j)\) 表示 \(f(u, 0) = i, \max\{f(u, 0), f(u, 1)\} = f(u, 0) + j\) 的方案数。

转移时同样是考虑逐个加入子结点 \(v\),式子挺好推就懒得写了。

初值: \(\forall u, f(u, 0, j) = 1(j \in [1, k])\)。

答案: \(ans_l = \sum\limits_{i + j = l} F(1, i, j)\)。

跑自身 \(\mathcal O(n)\) 树形 DP 的时候,每层的时间复杂度是 \(\mathcal O(n^2k^4)\),根据主定理,取大的单层时间复杂度,总时间复杂度 \(\mathcal O(n^2k^4)\)。

实际实现时还可以在转移对为 \(0\) 的状态剪枝,飞快!

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

constexpr int N = 1e3 + 10, K = 5 + 1, MOD = 1e9 + 7;

int n, k, sz[N], f[N][N * K][K], fu[N * K][K];

vector<int> G[N];
inline void add(int u, int v) {G[u].emplace_back(v), G[v].emplace_back(u);}

void dfs(int u, int fa) {
    sz[u] = 1;
    for (int j = 1; j <= k; j++) f[u][0][j] = 1;
    for (int v : G[u]) if (v != fa) {
        int maxi = k * sz[u];
        dfs(v, u); sz[u] += sz[v];
        int maxp = k * sz[v];
        for (int i = 0; i <= maxi; i++) {
            for (int j = 0; j <= k; j++) if (f[u][i][j]) {
                for (int p = 0; p <= maxp; p++) {
                    for (int q = 0; q <= k; q++) if (f[v][p][q]) {
                        int x = i + p + q, y = max(j - q, 0);
                        fu[x][y] = (fu[x][y] + 1ll * f[u][i][j] * f[v][p][q]) % MOD;
                    }
                }
            }
        }
        maxi = k * sz[u];
        for (int i = 0; i <= maxi; i++) for (int j = 0; j <= k; j++) f[u][i][j] = fu[i][j], fu[i][j] = 0;
    }
}

int main() {
    // freopen("2.in", "r", stdin), freopen("a.out", "w", stdout);
    ios_base::sync_with_stdio(0); cin.tie(nullptr), cout.tie(nullptr);
    cin >> n >> k;
    for (int i = 1, u, v; i < n; i++) cin >> u >> v, add(u, v);
    dfs(1, 0); n *= k;
    for (int i = 1; i <= n; i++) {
        ll ans = 0;
        for (int j = max(i - k, 0); j <= i; j++) ans += f[1][j][i - j];
        cout << ans % MOD << '\n';
    }
    return 0;
}

标签:SDOI,SXOI2022,int,max,复杂度,P8352,mathcal,sum,DP
From: https://www.cnblogs.com/chy12321/p/17998787

相关文章

  • P8350 [SDOI/SXOI2022] 进制转换
    记\(len_x\)为\(x\)在\(a\)中出现的次数,显然有\(\mathcalO(nq)\)的暴力,拿下\(20\)分。感觉用数据结构难以维护,考虑根号做法。根号做法有一个阈值\(L\),然后分讨(钦定\(len_x\lelen_y\)):\(len_x\lelen_y\leL\)直接暴力做,时间复杂度\(\mathcalO(L)\)。\(L......
  • [SDOI2019] 移动金币(阶梯博弈)
    题面一枚金币向左移若干格等价若干个空格向右移一个金币,终状态为所有空格在最右,转换为阶梯博弈阶梯博弈每个阶梯上有若干枚石子,每次操作将同个阶梯的任意石子向下移一个阶梯,不能操作者输等价对奇数阶梯做Nim博弈先手按Nim博弈操作。若对方移动偶数阶梯,则将对方移动石子继续下......
  • P5618 SDOI2015 道路修建题解
    题目分析虽然数据范围只有\(n\le60000\),但是完全可以直接用线段树做。首先考虑那种状态的图在左边和右边加入节点和边之后可以连通。容易发现,这种图有这两个性质:至少有一条路径,经过最左端和最右端中的点。所有点至少和最左端和最右端的点连通。于是可以划分成以下几种状态......
  • P5362 [SDOI2019] 连续子序列 题解--zhengjun
    题面传送门提供一种和其他题解完全不同的解法。记\(P_0\)为题中给出的序列,\(P_1\)为\(P_0\)取反的结果。记\(S_{l\simr}\)表示\(S_lS_{l+1}\dotsS_{r}\)。方便起见,\(P\)下标从\(0\)开始,其余的串都是从\(1\)开始。这里用\(P_{0,i}=\operatorname{popcount(i)}......
  • [SDOI2017] 天才黑客
    [SDOI2017]天才黑客题目背景SD0062号选手小Q同学为了偷到SDOI7012的试题,利用高超的黑客技术潜入了SDOI出题组的内联网的中央控制系统,然而这个内联网除了配备有中央控制系统,还为内联网中的每条单向网线设定了特殊的通信口令,这里通信口令是一个字符串,不同网线的口令可能不同。这......
  • 洛谷 P5359 [SDOI2019] 染色
    洛谷传送门LOJ传送门dp好题。首先有一个显然的状态,设\(f_{i,x,y}\)为第\(i\)列上下两格的颜色分别为\(x,y\)的方案数。但是这样做时间复杂度至少为\(O(nm^2)\),无法接受。注意到全\(0\)列的转移是重复的。我们可以试着只在两个相邻非全\(0\)列转移。这样我们需......
  • 题解 [SDOI2016] 游戏
    可以看出来出题人很想出一道把李超和别的什么东西凑起来的题目,于是给了这么一个缝合怪。https://www.luogu.com.cn/problem/P4069符号有点混乱。比如箭头又可以表示路径又可以表示赋值,代入语境应该还是好理解的。看到\(a\timesdis+b\)就应激反应出来是李超了,看到\(s\to......
  • [SDOI2010] 大陆争霸
    [SDOI2010]大陆争霸屁话真多。第一眼看上去好像是最短路加了个强制拓扑。也就是说当结界还没被破坏的时候,已经到达的机器人只能干等着。在dijkstra中,机器人所在的点可以更新最短路。但拓扑图上该点的入度不为\(0\),即结界产生器没有被全部破坏时,不能入队。当炸掉一个结界......
  • [SDOI2010] 大陆争霸 题解
    [题目传送门](https://www.luogu.com.cn/problem/P2446)#解法由题可知,一个城市$u$保护城市$v$,所以建一条边$u\tov$表示城市$u$保护城市$v$,因为题目说保证有解,所以建的图一定是一个**有向无环图$DAG$**。再在此基础上求出最短路径。具体过程为设$dis_u$表示实际到达(攻破)$u$的最......
  • [SDOI2017] 树点涂色
    [SDOI2017]树点涂色题目描述Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:1x表示把点\(x\)到根节点的路......