当前位置: 首页 > news >正文

题解:AT_abc311_h [ABC311Ex] Many Illumination Plans

题意:给出一棵树,每个节点有权值,重量和颜色,问对于每个子树 \(u\),选出一个包含 \(u\) 的虚树,满足重量之和 \(\le X\),相邻两个点颜色不同且权值和最大。

做法:

首先我们会一个非常平凡的 \(O(nX^2)\) 做法,但是这样怎么找都需要一个没有任何性质的 \((max,+)\) 卷积,显然很完蛋,我们考虑为什么会这么慢,因为我们需要枚举节点重量的一个线性组合,所以导致会多个加入,这样很爆炸。

我们不妨先考虑一个更基础的问题,P2014。这个题的题意就是选节点必须选父亲,那么我们考虑这样一个 dp。\(dp_{i,j}\) 代表子树 \(i\),里面选了 \(j\) 个节点,但是这样不够,没有优化空间,我们考虑在做 dp 的时候将 dp 值直接传给儿子,再对自己进行贡献。但是为了保证父亲也选了,我们强制限定向下传的时候 \(1\rightarrow i\) 路径上的若干个点都必选,前面的贡献算过了,在下传的时候加上儿子的权即可,细节可以看代码。

考虑这样做的正确性,因为如果我们进入一个子树,我们就立刻算掉了贡献保证一定有,而保证了这样之后其实元素间就没有什么其他限制了。

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 305;
int dp[maxn][maxn], val[maxn], n, m, dep[maxn];
vector<int> e[maxn];
void dfs(int u) {for (int i = 0; i < e[u].size(); i++) {int v = e[u][i]; dep[v] = dep[u] + 1;for (int j = dep[u] + 1; j <= m; j++)dp[v][j] = dp[u][j - 1] + val[v];dfs(v);for (int j = dep[u] + 1; j <= m; j++)dp[u][j] = max(dp[u][j], dp[v][j]);}
}
signed main() {cin >> n >> m; m++;for (int x, i = 1; i <= n; i++)cin >> x >> val[i], e[x].push_back(i);dep[0] = 1;dfs(0);cout << dp[0][m] << endl;return 0;
}

然后我们考虑对这个题也施加这个 trick,那么先考虑暴力怎么做,\(dp_{u,0/1,i}\) 代表 \(u\) 子树内最上层的颜色为 \(0/1\),重量为 \(i\),最大的权值之和。如果没有颜色直接秒了,考虑有颜色怎么办。

我们如果直接下传,那么会出现一个问题,可能我们会在子树 \(v\) 中从 \(dp_{u,0}\) 转移来一个 \(1\) 颜色的点,\(w\) 子树中又有一个 \(0\) 颜色的,这样就出问题了。

这里有一步天才的想法,我们直接下传 \(dp_{v,0} = dp_{v,1}=dp_{u,0}\),再下传 \(dp_{v,0} = dp_{v,1}=dp_{u,1}\),然后前者只取 \(dp_{v,0}\),后者只取 \(dp_{v,1}\),分讨一下下面的情况发现确实是可以覆盖所有情况的!

但是问题来了,这样的复杂度是 \(\sum 2^{dep}\) 的,那么既然是深度相关,那么完全可以用重链剖分优化一下,启发式一下,直接继承重儿子然后再对于其他的考虑。

分析复杂度,\(T(n) = T(a_1)+2\sum T(a_i)+O(X)\),那么我们应该让后面的 \(\times 2\) 的部分尽量大,那么就让子树间平均,那么就是 \(T(n) = (2k-1)T(\frac{n}{k})+O(X)\),由主定理得到复杂度为 \(O(n^{\log_{k}2k-1}X)\)\(k=2\) 时取到最大,为 \(O(n^{1.59}X)\)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 205, inf = 9e18; 
int n, x, p[maxn], v[maxn], w[maxn], c[maxn], sz[maxn], son[maxn];
vector<int> e[maxn];
void dfs1(int u, int fa) {sz[u] = 1;for (int i = 0; i < e[u].size(); i++) {int v = e[u][i];dfs1(v, u), sz[u] += sz[v];if(sz[son[u]] < sz[v])son[u] = v;}	
}
int ans[maxn];
pair<vector<int>, vector<int> > dfs(int u, vector<int> dp, bool use) {if(use) {for (int i = 0; i < e[u].size(); i++) {int v = e[u][i];if(v == son[u])continue;dfs(v, dp, use);}}vector<int> f[2];if(son[u]) {pair<vector<int>, vector<int> > p = dfs(son[u], dp, use);f[0] = p.first, f[1] = p.second;for (int i = 0; i < e[u].size(); i++) {int v = e[u][i];if(v == son[u])continue;f[0] = dfs(v, f[0], 0).first;f[1] = dfs(v, f[1], 0).second;}}elsef[0] = f[1] = dp;if(use) {for (int i = x; i >= w[u]; i--) ans[u] = max(ans[u], f[c[u] ^ 1][i - w[u]] + v[u]);}for (int i = x; i >= w[u]; i--) f[c[u]][i] = max(f[c[u]][i], f[c[u] ^ 1][i - w[u]] + v[u]);return make_pair(f[0], f[1]);
}
signed main() {cin >> n >> x;for (int i = 2; i <= n; i++)cin >> p[i], e[p[i]].push_back(i);dfs1(1, 0);for (int i = 1; i <= n; i++)cin >> v[i] >> w[i] >> c[i];vector<int> v; v.resize(x + 1);for (int i = 1; i <= x; i++)v[i] = -inf;dfs(1, v, 1);for (int i = 1; i <= n; i++)cout << ans[i] << endl;return 0;
}
http://www.jsqmd.com/news/6540/

相关文章:

  • 2025-9-27 提高组模拟赛 div2
  • 植物大战僵尸融合版下载安装教程【PC/安卓/iOS 完整攻略 + 常见问题解决】 - 详解
  • 两场div3 逆向思维
  • 详细介绍:(基于江协科技)51单片机入门:5.定时器
  • part2
  • SuperMap iObjects .NET 11i 二次开发(十五)—— 类型转换之面转点 - 教程
  • 题解:B4410 [GESP202509 一级] 金字塔
  • 9.30总结
  • pytorch基本运算-torch.normal()函数输出多维材料时,如何绘制正态分布函数图
  • AT_agc035_c [AGC035C] Skolem XOR Tree
  • 2025.9.30总结 - A
  • Harbor磁盘空间清理指南:如何安全清理半年前的镜像 - 详解
  • 详细介绍:第14章 AI Agent——构建自主智能助理
  • Java入门级教程21——Java 缓存技术、RMI远程办法调用、多线程分割大档案
  • PowerToys新工具Light Switch:让Windows自动切换明暗主题
  • java从word模板生成.doc和.wps文件
  • 炼石#8 T1
  • 详细介绍:《C++ Primer Plus》读书笔记 第二章 开始学习C++
  • AI+手搓第一个AI Agent“AI胜铭兰”
  • 基于JDK17的GC调优策略
  • 【MC】我的世界schematic方块坐标提取转为json
  • 电脑开机显示屏表现无信号怎么办 原因及解决方法
  • JDK17新特性梳理
  • 函数-参数+作用域
  • 用 Nim 实现英文数字验证码识别
  • 思路探索:当大型语言模型遇见数据分析的现实挑战 - 教程
  • 抓紧上车,别再错过啦, Github 开源后台管理平台,Naive UI !!!
  • 实用指南:电子电气架构 --- 智能座舱域环境感知和人机交互系统
  • 【机器学习】朴素贝叶斯法 - 实践
  • 【Rust GUI开发入门】编写一个本地音乐播放器(8. 从文件中提取歌曲元信息) - Jordan