P8119 「Wdoi-1.5」幻想乡游览计划

news/2024/11/16 22:10:36/文章来源:https://www.cnblogs.com/cjoierzdc/p/18549900

不妨考虑树的情况,对于图只要取一棵生成树即可。

\(k\le 4n\) 是容易的,两个点分别 dfs 就是 \(\le 4n\) 次。

对于 \(k\le 3n\),考虑一个做法:一个人去遍历整棵树,每次拓展新点时交换。不难证明正确性,次数 \(\le 3n\)

考虑优化这个策略。注意到其中一个点一直在根,这非常浪费。事实上我们可以两个点同时递归两棵子树,每次同时走到一个新点然后交换。

但是这个优化在两棵子树大小差距过大时用处不大,考虑取重心,每个子树划分给某个人去遍历。假设分给两人的大小之和分别为 \(S_1\)\(S_2\),那么总次数就是 \(2\times(S_1+S_2)+\max(S_1,S_2)\)

考虑从大往小考虑每棵子树,每次划分给较小的 \(S\),可以证明 \(\max S\le \dfrac{2}{3}n\),总次数 \(\le\dfrac{8}{3} n\)

code
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
void file() {freopen("1.in", "r", stdin);freopen("1.out", "w", stdout);
}
using ll = long long;const int kL = 5e5 + 5;
int n, m;
array<int, kL> siz;
array<bool, kL> vis;
array<vector<int>, kL> g;
string A = "Ran", B = "Chen";struct DSU {array<int, kL> fa;DSU() { iota(ALL(fa), 0); }int find(int x) {return (fa[x] == x) ? x : (fa[x] = find(fa[x]));}void merge(int x, int y) { fa[find(x)] = find(y); }
}dsu;int findrt(int x, int Fa) {int mx = 0, rt = 0; siz[x] = 1;for(int to : g[x]) {if(to == Fa) continue;if(int tmp = findrt(to, x))rt = tmp;siz[x] += siz[to];mx = max(mx, siz[to]);}mx = max(mx, n - siz[x]);return (mx * 2 <= n) ? x : rt;
}void dfs(int x, int Fa) {if(Fa) g[x].erase(find(ALL(g[x]), Fa));for(int to : g[x]) dfs(to, x);
}vector<pair<string, int>> ans;void push(int x, vector<int>& buc) {buc.push_back(x);for(int to : g[x]) {push(to, buc);buc.push_back(x);}
}vector<int> vx, vy;void solve(int x, int Fa) {if(g[x].empty()) return ;sort(ALL(g[x]), [&](int a, int b) { return siz[a] > siz[b]; });for(int to : g[x]) {vector<int> buc;push(to, buc);buc.push_back(x);if(vx.size() < vy.size()) {for(int i : buc) vx.push_back(i);}else {for(int i : buc) vy.push_back(i);}}
}void getans() {int i, j;for(i = j = 0; (i < vx.size()) && (j < vy.size()); ) {int a = vx[i], b = vy[j];if(vis[a]) { ans.emplace_back(A, a); i++; }if(vis[b]) { ans.emplace_back(B, b); j++; }if(!vis[a] && !vis[b]) {i++, j++, vis[a] = vis[b] = 1;ans.emplace_back(A, a);ans.emplace_back(B, b);ans.emplace_back("Swap", -1), swap(A, B);}}for(; i < vx.size(); i++) {int p = vx[i];if(vis[p]) ans.emplace_back(A, p);else {vis[p] = 1;ans.emplace_back(A, p);ans.emplace_back("Swap", -1), swap(A, B);}}for(; j < vy.size(); j++) {int p = vy[j];if(vis[p]) ans.emplace_back(B, p);else {vis[p] = 1;ans.emplace_back(B, p);ans.emplace_back("Swap", -1), swap(A, B);}}
}int main() {// file();ios::sync_with_stdio(0), cin.tie(0);cin >> n >> m;for(int i = 1, u, v; i <= m; i++) {cin >> u >> v;if(dsu.find(u) != dsu.find(v)) {dsu.merge(u, v);g[u].push_back(v);g[v].push_back(u);}}ans.reserve(3 * n);vx.reserve(2 * n);vy.reserve(2 * n);int root = findrt(1, 0);assert(findrt(root, 0) == root);dfs(root, 0), solve(root, 0), getans();cout << root << " ";cout << ans.size() << "\n";for(auto k : ans) {if(~k.second) cout << k.first << " " << k.second << "\n";else cout << k.first << "\n";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/834813.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Astro搭建个人博客

大家好,我是Yinph。 今天给大家带来一篇关于如何使用Astro快速搭建个人博客的文章。 直接进入正题: 一、准备工作在Astro挑选一个自己心仪的博客模板 安装nodejs 一个GitHub账号,并建一个仓库 一个Cloudflare账号 一个Netlify账号 最好下载VS Code,方便以后修改博客:::note…

【C++复习】栈-下篇

大家好,这里是不会写开场白的Yinph。 今天我们先来复习一下中缀表达式、前缀表达式和后缀表达式,以及如何用栈来实现它们之间的运算。 一、中缀表达式 ‌‌中缀表达式‌是一种算术或逻辑公式的表示方法,其中操作符位于操作数的中间。这种表示方法符合人们的日常书写习惯,因…

gofiber: 模板:判断if条件

一,代码: 1,controller func (dc *ArticleController) GetArticle(c *fiber.Ctx) error {// 处理获取文章的逻辑article := new(Article)article.Id = 1article.Title = "三国演义金圣叹批本"article.Author = "罗贯中"user:=c.Query("user")m…

starrycan的pwn随笔——ELF文件和延迟绑定机制

一.ELF文件结构 0x01什么是ELF文件 1.linux环境中,二进制可持性文件的类型是ELF(Executable and LinkableFormat)文件。类似windows下的exe 2.elf文件的格式比较简单,我们需要了解的就是elf文件中的各个节、段等概念 3.程序elf的基本信息存在于elf的头部信息中,这些信息包括…

达梦数据库DM管理工具如何浏览数据,用条件筛选数据

前言 大家好,我是小徐啊。达梦数据库是我们一款常用的国产数据库,我之前一直在使用它。用起来和mysql和postgresql比起来,还是差不多的。而且它自带了数据库连接工具DM管理工具,使我们很方便的连接它。 今天,小徐就来介绍下如何用DM管理工具浏览数据,并且用条件去筛选数据…

标注图片怎么导出VOC格式和COCO格式

图片怎么标注参考 https://www.cnblogs.com/minseo/p/18549804下载 从github下载代码,或压缩包# git clone https://github.com/LabelMe/labelme转换 示例文件在以下路径# labelme-main\examples\instance_segmentation目录以及各个目录的用途如下打过标签的图片和json文件放以…

vscode Markdown文件如何使代码超出屏幕可视区域不换行

在编写Markdown文件的表格时,单元格内过长的内容会使得行超出可视区域,Markdown处理方式为单行用多行表示,如下图所示:这样会破坏表格的可读性,利用快捷键Alt+Z,可变为如下形式:使得表格每列对齐以增加可读性

20222325 2024-2025-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 本实践目标是掌握metasploit的用法。 指导书参考Rapid7官网的指导教程。 https://docs.rapid7.com/metasploit/metasploitable-2-exploitability-guide/ 下载官方靶机Metasploitable2,完成下面实验内容。 (1)前期渗透 ①主机发现(可用Aux中的arp_sweep,search一…

[Linux]gdb基本使用

gdb基本使用 前提 gcc/g++编译出的程序默认是realease版本,要使用gdb调试,首先要在编译的时候加上-g选项。使用readelf -S [程序名]查看可执行文件的节区信息。使用gdb [程序名]:开始调试。q:退出调试。list/l [行号]:从给定的位置显示程序的源代码,每次十行。break/b [行…

美团商家联系电话采集软件团购外卖信息批量提取器

定义目标:明确需要采集的数据,如商家名称、地址、评分、销量等。 分析页面结构:通过浏览器的开发者工具,分析美团团购或外卖页面的HTML结构,找出包含所需数据的标签。 模拟用户请求:使用requests库模拟用户访问美团页面,可能需要处理登录、反爬虫机制(如Cookies、Heade…

# 团队作业4——项目冲刺-6

团队作业4——项目冲刺-6信息项 内容课程名称 广工计院计科34班软工作业要求位置 作业要求作业目标 在七天敏捷冲刺中,完成工大严选开发,记录每日进展和问题,更新燃尽图、签入代码,并发布集合日志总结成果GitHub链接 GitHub一、团队简介队名:小飞棍队团队成员:姓名 学号罗…

20222427 2024-2025-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 1.1 本周内容总结使用了Metasploit框架,其是一个功能强大的渗透测试框架。在使用的过程当中,Metasploit 提供了种类繁多的攻击模块,涵盖了远程代码执行、服务拒绝、提权等多种攻击方式,支持对多种操作系统和应用程序进行测试。除了漏洞利用,它还具备强大的后渗…