NC20811 蓝魔法师
题目
题目描述
“你,你认错人了。我真的,真的不是食人魔。”--蓝魔法师
给出一棵树,求有多少种删边方案,使得删后的图每个连通块大小小于等于k,两种方案不同当且仅当存在一条边在一个方案中被删除,而在另一个方案中未被删除,答案对998244353取模
输入描述
第一行两个整数n,k, 表示点数和限制
2 <= n <= 2000, 1 <= k <= 2000
接下来n-1行,每行包括两个整数u,v,表示u,v两点之间有一条无向边
保证初始图联通且合法
输出描述
共一行,一个整数表示方案数对998244353取模的结果
示例1
输入
5 2 1 2 1 3 2 4 2 5
输出
7
题解
知识点:树形dp,背包dp,计数dp。
显然是个树上背包,但涉及组合计数。
设 表示以 为根的子树划分成大小不大于 连通块,且 所在连通块大小为 的方案数。这道题要剪枝,转移方程我用了刷表法。下面代码有打表和刷表的对比,明显刷表法更容易写出最佳的循环边界。转移方程为:
- 连接 , 与 用乘法原理合并,最后得到 ,显然 要小于等于 。 , ,两者都要倒序遍历保证 是倒序的。
- 断开 , 的方案加上 的所有方案数。为了防止 的更新影响 ,因此这个更新要在一次 的更新最后执行。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; const int mod = 998244353; int n, k; vector<int> g[2007]; int dp[2007][2007], sz[2007]; /* void dfs(int u, int fa) { dp[u][1] = 1; sz[u] = 1; for (auto v : g[u]) { if (v == fa) continue; dfs(v, u); sz[u] += sz[v]; int sumv = 0; for (int i = 1;i <= sz[v];i++) sumv = (sumv + dp[v][i]) % mod; for (int i = min(sz[u], k);i >= 1;i--) { dp[u][i] = 1LL * dp[u][i] * sumv % mod;///断开 for (int j = max(1, sz[v] + i - sz[u]);j <= min({ i, k,sz[v] });j++) ///链接 dp[u][i] = (dp[u][i] + 1LL * dp[u][i - j] * dp[v][j]) % mod; } } } */ ///复杂度和常数比上面一种方式少一点,甚至比上面边界好写很多 void dfs(int u, int fa) { dp[u][1] = 1; sz[u] = 1; for (auto v : g[u]) { if (v == fa) continue; dfs(v, u); int sumv = 0; for (int i = 1;i <= sz[v];i++) sumv = (sumv + dp[v][i]) % mod; for (int i = min(sz[u], k);i >= 1;i--) { for (int j = min(sz[v], k);j >= 1;j--) { if (i + j > k) continue;///也可以用tmp暂存的方法,然后顺序更新,就可以直接break,否则只能倒叙 dp[u][i + j] = (dp[u][i + j] + 1LL * dp[u][i] * dp[v][j]) % mod; } dp[u][i] = 1LL * dp[u][i] * sumv % mod; } sz[u] += sz[v]; } }///复杂度 O(nk^2),剪枝以后复杂度不变但常数会少巨多,因为少遍历了很多不可能的状态 int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> n >> k; for (int i = 1;i < n;i++) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } dfs(1, 0); int ans = 0; for (int i = 1;i <= k;i++) ans = (ans + dp[1][i]) % mod; cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16619960.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧