CF1833G Ksyusha and Chinchilla

题目链接

题解

知识点:贪心,树形dp。

3n 时,显然无解。

考虑一种贪心策略,从叶子节点往上只,要以当前节点为根的子树大小能被 3 整除,就立刻切除这棵子树,若最后切除次数刚好为 n31 ,则有解。

考虑证明:

  1. 显然,若根据我们的策略成功划分,则一定满足条件,即有解。
  2. 若不满足,则一定存在一个子树除掉满足我们策略的部分后,仍然剩余 >3 个节点,此时子树的每个子树深度不会超过 2 ,且一定没有分叉,是无法进行任何切割的,因此无解。

时间复杂度 O(n)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<pair<int, int>> g[200007];
int sz[200007];
vector<int> ans;
void dfs(int u, int fa) {
sz[u] = 1;
for (auto [v, id] : g[u]) {
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[v] % 3 == 0) ans.push_back(id);
}
}
bool solve() {
int n;
cin >> n;
ans.clear();
for (int i = 1;i <= n;i++) g[i].clear();
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g[u].push_back({ v,i });
g[v].push_back({ u,i });
}
if (n % 3) return false;
dfs(1, 0);
if (ans.size() != n / 3 - 1) return false;
cout << n / 3 - 1 << '\n';
for (auto id : ans) cout << id << ' ';
cout << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
posted @   空白菌  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示