CF2006A Iris and Game on the Tree
题解
知识点:贪心,博弈论。
一个 串中 的个数差只与首尾两个字符相关,若首尾字符相同,则个数差为 ,否则为 或 。因此,树上除了根节点和叶子节点的 是不影响叶子节点权值的(但可能影响策略,导致答案不一样),我们只需要考虑叶子节点和根节点的情况即可。
设 分别为值为 的叶子节点个数。
如果根节点不是 ,那么答案显然为与根节点值相反的叶子节点数,加上 。接下来考虑根节点是 的情况。
当 时,不妨设 ,先手有如下几种策略:
- 先手第一步确定根节点的值为 ,此时答案为 。
- 先手第一步确定根节点的值为 ,此时答案为 。
- 先手第一步确定一个叶子节点为 ,那么后手可以确定根节点为 ,此时答案为 。
- 先手第一步确定一个叶子节点为 ,那么后手可以确定根节点为 ,此时答案为 。
显然第一种策略答案最优。
当 时,有如下几种情况:
- 不存在非根节点和叶子节点的 ,无论如何答案都为 。
- 存在一个非根节点和叶子节点的 ,先手可以选择一个非根节点和叶子节点的 随意赋值,后手无论如何赋值,答案都为 。
- 存在多个非根节点和叶子节点的 ,如果数量为偶数,则与不存在的情况等价,否则与存在一个的情况等价。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int deg[100007]; bool solve() { int n; cin >> n; for (int i = 1;i <= n;i++) deg[i] = 0; for (int i = 2;i <= n;i++) { int u, v; cin >> u >> v; deg[u]++; deg[v]++; } string s; cin >> s; s = "?" + s; int cnt[3] = {}; for (int i = 2;i <= n;i++) if (deg[i] == 1) cnt[s[i] == '?' ? 2 : s[i] == '1']++; if (s[1] != '?') cout << cnt[s[1] == '0'] + (cnt[2] + 1) / 2 << '\n'; else { if (cnt[0] == cnt[1]) { int delta = count(s.begin() + 1, s.end(), '?') - cnt[2] - 1; cout << cnt[0] + (cnt[2] + (delta & 1)) / 2 << '\n'; } else cout << max(cnt[0], cnt[1]) + cnt[2] / 2 << '\n'; } return true; } int main() { std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int t = 1; cin >> t; while (t--) { if (!solve()) cout << -1 << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/18426981
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧