尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

CF2127H 23 Rises Again

CF2127H 23 Rises Again
📅 发布时间:2026/6/18 19:35:03

记一个 qiuzx 在 CF 上发的做法。

考虑建出这个图的圆方树,在圆方树上 dp。\(dp_{i,0/1/2}\) 表示以 \(i\) 为根的子树,\(i\) 的覆盖次数(如果 \(i\) 是方点记录的就是 \(fa_i\) 的覆盖次数)。

对于圆点处的 dp 合并是容易的。

对于方点处的合并看起来不是很好做。题目限制经过每个点的环 \(\le 5\) 个,这个限制对于一个点双是很严的。

对于一个点双,首先有每个点的度数 \(\le 3\),否则就至少有 \(\binom{4}{2}=6\) 个环。

再手玩一下,可以发现度数 \(=3\) 的点也是不多的。似乎可以证明最多只有 \(4\) 个点是满足度数 \(=3\) 的。

注意到如果每个点度数 \(\le 2\) 就非常好做了,而我们最终保留的图中每个点度数也 \(\le 2\),于是考虑对于每个度数为 \(3\) 的点,我们都删掉一条邻边,这样就满足度数 \(\le 2\) 了。

然后整个点双就只剩若干个环和链了,这个可以直接 dp 一下链覆盖的形态,容易做到线性。

总复杂度是 \(O(3^4n^2)\),可以精细实现到 \(O(3^4n)\),但是不必要。

在本题的限制下,如果每个点双 \(\le4\) 个度数 \(=3\) 点成立,那么可以说明 \(m\le \frac{5}{3}n\)。此时取出一棵 dfs 树,然后对于非树边搜是否选择,对树做 dp 应该可以做到 \(O(2^{\frac{2}{3}n}n)\)。

#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int> ;
template <typename T> void Chkmin(T &x, T y) { x = min(x, y); }const int inf = 1e9;
const int kN = 65;
const int pw3[] = {1, 3, 9, 27, 81, 243, 729};
int n, m, tot, num, tp;
vector<pii> g[kN];
int dfn[kN], low[kN], fa[kN], stk[kN], dp[kN][3];
vector<int> tr[kN];void Clear() {tot = num = 0;fill(dfn, dfn + kN, 0);fill(g, g + kN, vector<pii> ());fill(tr, tr + kN, vector<int> ());
}void Link(int f, int x) { tr[fa[x] = f].push_back(x); }
void Tarjan(int x) {dfn[x] = low[x] = ++tot;stk[++tp] = x;for(pii k : g[x]) {int to = k.first;if(!dfn[to]) {Tarjan(to);Chkmin(low[x], low[to]);if(low[to] >= dfn[x]) {int id = n + ++num, t;Link(x, id);do Link(id, t = stk[tp--]);while(t != to) ;}}else Chkmin(low[x], dfn[to]);}
}bool ban[kN], vis[kN];
vector<pii> ng[kN];
vector<int> gg[kN];void DFS2(int x, vector<int> &v) {vis[x] = 1;v.push_back(x);for(int to : gg[x]) {if(!vis[to]) DFS2(to, v);}
}int f[kN][3];
int ff[kN][3][3];int F(vector<int> id) {int siz = id.size();for(int i = 0; i < siz; i++) fill(f[i], f[i] + 3, inf);int p = id[0];f[0][0] = min(dp[p][0], dp[p][1]);f[0][2] = min({dp[p][0] + 1, dp[p][1] + 1, dp[p][2]});for(int i = 1; i < siz; i++) {int p = id[i];int *g = f[i - 1];f[i][0] = g[2] + min(dp[p][0], dp[p][1]);f[i][1] = min(g[0], g[1]) + dp[p][0];f[i][2] = min(min({g[0], g[1], g[2]}) + min(dp[p][0], dp[p][1]) + 1, g[2] + dp[p][2]);}return f[siz - 1][2];
}
int G(vector<int> id) {int siz = id.size();for(int i = 0; i < siz; i++) {for(int j : {0, 1, 2}) fill(ff[i][j], ff[i][j] + 3, inf);}ff[0][0][0] = ff[0][1][1] = ff[0][2][2] = 0;for(int i = 1; i < siz; i++) {int p = id[i];for(int j : {0, 1, 2}) {int *f = ff[i][j], *g = ff[i - 1][j];f[0] = g[2] + min(dp[p][0], dp[p][1]);f[1] = min(g[0], g[1]) + dp[p][0];f[2] = min(min({g[0], g[1], g[2]}) + min(dp[p][0], dp[p][1]) + 1, g[2] + dp[p][2]);}}int res = 0;int p = id[0];for(int i : id) res += dp[i][0];int f[3][3];memcpy(f, ff[siz - 1], sizeof(f));Chkmin(res, f[0][2] + min(dp[p][0], dp[p][1]));Chkmin(res, min(f[1][0], f[1][1]) + dp[p][0]);Chkmin(res, min({f[2][0], f[2][1], f[2][2]}) + min(dp[p][0], dp[p][1]) + 1);Chkmin(res, f[2][2] + dp[p][2]);return res;
}int Calc(int all) {fill(vis + 1, vis + n + 1, 0);fill(gg + 1, gg + n + 1, vector<int> ());for(int i = 1; i <= n; i++) {if(!((all >> i) & 1)) continue;for(pii k : ng[i]) {int to, id;tie(to, id) = k;if(((all >> to) & 1) && !ban[id]) gg[i].push_back(to);}}int res = 0;for(int i = 1; i <= n; i++) {if(!((all >> i) & 1) || vis[i]) continue;if(gg[i].size() <= 1) {vector<int> node;DFS2(i, node);res += F(node);}}for(int i = 1; i <= n; i++) {if(!((all >> i) & 1) || vis[i]) continue;vector<int> node;DFS2(i, node);res += G(node);}return res;
}int p3[kN], deg[kN];void DP(int rt, int *f, int all) {fill(deg + 1, deg + n + 1, 0);fill(ng + 1, ng + n + 1, vector<pii> ());for(int i = 1; i <= n; i++) {if(!((all >> i) & 1)) continue;for(pii k : g[i]) {int to = k.first;if((all >> to) & 1) ng[i].push_back(k);}}int c3 = 0;for(int i = 1; i <= n; i++) {if(ng[i].size() == 3) p3[++c3] = i;}for(int i = 0; i < pw3[c3 + 1]; i += 3) {fill(ban + 1, ban + m + 1, 0);for(int j = 1; j <= c3; j++) {int w = i / pw3[j] % 3;ban[ng[p3[j]][w].second] = 1;}dp[rt][2] = 0, dp[rt][0] = dp[rt][1] = inf;Chkmin(f[0], Calc(all));dp[rt][1] = 0, dp[rt][0] = dp[rt][2] = inf;Chkmin(f[1], Calc(all) - 1);dp[rt][0] = 0, dp[rt][1] = dp[rt][2] = inf;Chkmin(f[2], Calc(all));}
}void DFS(int x) {for(int to : tr[x]) DFS(to);if(x <= n) {int old[3];dp[x][0] = dp[x][1] = 0, dp[x][2] = 1;for(int to : tr[x]) {memcpy(old, dp[x], sizeof(old));int *f = old, *g = dp[to];dp[x][0] = f[0] + g[0];dp[x][1] = min(f[0] + g[1], f[1] + g[0]);dp[x][2] = min({f[1] + g[1] + 1, f[0] + g[2], f[2] + g[0]});}}else {dp[x][0] = dp[x][1] = dp[x][2] = inf;int all = (1 << fa[x]);for(int to : tr[x]) all |= (1 << to);DP(fa[x], dp[x], all);}Chkmin(dp[x][1], dp[x][0]);Chkmin(dp[x][2], dp[x][1] + 1);
}void Solve() {Clear();cin >> n >> m;for(int i = 1; i <= m; i++) {int u, v;cin >> u >> v;g[u].emplace_back(v, i);g[v].emplace_back(u, i);}Tarjan(1);DFS(1);cout << n - dp[1][2] << "\n";
}int main() {
//  freopen("1.in", "r", stdin);
//  freopen("1.out", "w", stdout);ios::sync_with_stdio(0), cin.tie(0);int t;cin >> t;while(t--) Solve();return 0;
}

相关新闻

  • 为什么收集分析用户反馈比功能上线更重要?
  • Symfony学习笔记 - Symfony Documentation - The Basics(2)
  • 【分享+1】HarmonyOS官方模板优秀案例(第6期:商务办公 笔记应用)

最新新闻

  • 赛博格鼓手:机械臂协同演奏的技术实现与音乐应用
  • PL2303驱动兼容性终极指南:轻松搞定Windows 10/11黄色感叹号问题
  • “涪车出海”直达北非
  • 2026汉中防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配秦巴盆地多雨湿冷防冻防潮甄选指南 - 宅安选房屋修缮
  • OpenHarmony鸿蒙PC完成ohos-sdk适配自动签名编译rust_decimal三方库,用于高精度十进制浮点场景
  • 2026大理防水补漏靠谱服务商盘点:屋面/厨卫/外墙/地下室渗水维修详解,适配滇西高原大风长雨季防潮甄选指南 - 宅安选房屋修缮

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号