[CEOI2023] The Ties That Guide Us 题解

news/2024/11/15 19:12:58/文章来源:https://www.cnblogs.com/Scarab/p/18548514

Description

你用销售机器人的利润雇佣了一名助手,现在你准备好去拿走装有 CEOI 奖章的保险箱了。

保险箱位于一所由 \(n\) 个房间所组成的大学建筑内,这些房间由 \(n-1\) 扇门连接。每个房间都可以从其他任何房间到达,且每个房间最多与 \(3\) 扇门相连。

你和你的助手都有描述建筑物内房间相连情况的平面图,但是你们两个各自拥有的平面图虽然描述了相同的房间结构布局,但是房间和门的编号可能不同。

在比赛的第二天,委员会忙于处理赛时通知和选手提问。这将是接近装着奖牌的保险箱的完美机会。

你的助手会首先搜索整栋大楼。一旦他找到保险箱所在的房间,它就会给你留下前往那个房间的提示。由于手机不能带进赛场,他用了去年 BOI 留下的几乎无限供应的领带。由于这些领带完全相同无法区分,你能获得的信息就是他在任何给定房间里所留下的领带数量。由于一个房间内过多的领带非常可疑,因此任何单个房间内领带的最大数量应当尽可能少(参阅评分部分)。

之后,你计划在上厕所的时候溜出去,利用助手留下来的领带找到有保险箱的房间。保险箱藏在房间里,所以你进入带有保险箱的房间时,必须依靠领带识别这个房间;此外,由于“上厕所”时间过长会被发现,你必须尽快找到保险箱。你最多可以走过 \(d+30\) 扇门,其中 \(d\) 是你的初始位置到保险箱所在位置的最短路径上的门数量。若重复穿过同一扇门,则每次都计入。

因此,你需要编写一个程序,告诉助手需要在每个房间留下多少条领带,并引导你前往带有保险箱的房间。

Solution

首先对于 Sub2 只有一个点度数为 \(2\),所以可以直接取出这个唯一的点作为根,然后将目标点到根的路径颜色染黑。这样查询的时候只要暴力跳父亲,直到当前点颜色为黑,然后暴力枚举儿子,如果找到颜色为黑的儿子就往儿子跳,否则就是终点了。

不过这么做有个问题,就是找儿子的过程可能会浪费过多的询问次数,而注意到限制是 \(dist(s,t)+30\),由于每次试错会浪费两次,所以只能走错 \(15\) 步,为 \(O(\log n)\) 级别。

这启发我们重链剖分,每次跳子树大小最大的儿子,由于终点到 \(lca\) 路径上的轻儿子只有 \(O(\log n)\) 个,所以这样就是对的。

如果树没有特殊性质,可以利用树哈希的思想选定重心作为根,但是可能有两个重心,这时需要选取离起点更近的重心作为根。

查询时如果跳到根节点颜色还为白,就说明根是另一个重心,直接跳到那个重心即可。

总次数:\(d+2\log n\)

Code

#include <bits/stdc++.h>
#include "incursion.h"#ifdef ORZXKR
#include "grader.cpp"
#endifconst int kMaxN = 4.5e4 + 5;int n, safe;
int p[kMaxN], sz[kMaxN], mx[kMaxN];
bool vis[kMaxN];
std::vector<int> G[kMaxN], rt;void dfs1(int u, int fa) {sz[u] = 1, mx[u] = 0;for (auto v : G[u]) {if (v == fa) continue;dfs1(v, u);sz[u] += sz[v], mx[u] = std::max(mx[u], sz[v]);}mx[u] = std::max(mx[u], n - sz[u]);if (mx[u] <= n / 2) rt.emplace_back(u);
}void dfs2(int u, int fa) {p[u] = fa;for (auto v : G[u]) {if (v == fa) continue;dfs2(v, u);}
}void dfs3(int u, int fa) {vis[u] = 1;for (auto v : G[u]) {if (v == fa || vis[v]) continue;if (visit(v)) return dfs3(v, u);else visit(u);}
}std::vector<int> mark(std::vector<std::pair<int, int>> F, int safe) {n = (int)F.size() + 1;std::vector<int> vec(n, 0);for (int i = 1; i <= n; ++i) G[i].clear();for (auto [u, v] : F)G[u].emplace_back(v), G[v].emplace_back(u);rt.clear(), dfs1(1, 0), dfs2(rt[0], 0);for (int i = safe; i; i = p[i]) {vec[i - 1] = 1;if (rt.size() == 2 && (i == rt[0] || i == rt[1])) break;}return vec;
}void locate(std::vector<std::pair<int, int>> F, int cur, int t) {n = (int)F.size() + 1;for (int i = 1; i <= n; ++i) G[i].clear(), vis[i] = 0;for (auto [u, v] : F)G[u].emplace_back(v), G[v].emplace_back(u);rt.clear(), dfs1(1, 0), dfs2(rt[0], 0);for (int i = 1; i <= n; ++i)std::sort(G[i].begin(), G[i].end(), [&] (int x, int y) { return sz[x] > sz[y]; });for (; p[cur] && !t; t = visit(cur = p[cur])) vis[cur] = 1;vis[cur] = 1;if (!t) assert(cur == rt[0]), visit(cur = rt[1]);vis[cur] = 1;dfs3(cur, p[cur]);
}

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

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

相关文章

DHCP欺骗

DHCP 欺骗原理DHCP 协议(Dynamic Host Configuration Protocol) 动态主机配置协议:主要给客户机提供 TCP/IP 参数,包括:IP 地址、子网掩码、网关、DNS、租期工作原理应用层协议,基于UDP 主机向服务器 67 号端口发送 DHCP 请求 服务器响应给客户机的 68号端口配置设置DHCP 服…

Redis运行的时候碰到# Creating Server TCP listening socket *:6379: bind: No error

Redis运行的时候碰到# Creating Server TCP listening socket *:6379: bind: No error 解决方案: 1、启动redis客户端:redis-cli.exe。 2、执行关闭命令:输入shutdown3、执行退出命令:exit4、重新启动Redis输入:redis-server.exe redis.windows.conf

https实验

https 实验原理httphttps https = http + SSL/TLS •SSL: Secure Socket Layer 安全套接层 •TLS: Transport Layer Security 传输层安全协议加密方式:PKI(公钥基础设施)使用公钥技术和数字签名来保证信息安全由公钥密码算法、数字证书(Certificate)、CA(Certificate Aut…

手把手教你搭建OpenScenario交通场景(上)

经纬恒润动力学仿真软件ModelBase基于OpenScenario1.0标准,开发内嵌了场景编辑器,可用于对仿真测试过程中的车辆行驶道路模型之外,继续进行周边动态场景的搭建。 OpenScenario是一种专为自动驾驶系统仿真测试设计的场景描述语言,它基于XML格式,旨在提供一个标准化、…

动态规划题单2

第一个题单编辑到后面实在是太卡了,就新开了一个,以后应该也会 \(30\) 题为一个题单。 31.CF1580D Subsequence CF1580D Subsequence 不会笛卡尔树,但是看到题解区的妙妙解法...... 题目的式子非常大便,我们考虑把它翻译成人话: 一个子序列的价值为: \(sum*m - 每两个数及他…

java 反序列化 cc7 复现

java 反序列化 cc7 复现复现环境:common-collections版本<=3.2.1,java版本随意.cc7就是cc6换了一个出口,整体的逻辑没有太大的变化.在Lazymap之前的还那样,我们从如何触发Lazymap的get方法开始看起. AbstractMap 看他的equals方法 public boolean equals(Object o) { if (o…

告别Print,使用IceCream进行高效的Python调试

在Python开发实践中,调试是一个不可或缺的环节。如果采用print()语句来追踪程序执行流程,可能会遇到一个持续出现的异常情况,并且经过多次代码审查问题的根源仍然难以确定,这可能是因为随着终端输出信息的不断增加,这种调试方式的局限性逐渐显现。本文将介绍IceCream库,这…

浏览器

控制台 查看继承的样式 Inherited(继承) from xxx: 继承样式来自于xxx <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><title>Document</title><style>.font {font-size: 12px;}.font2 {fon…

团队项目Scrum冲刺-day5

一、每天举行站立式会议 站立式会议照片一张昨天已完成的工作成员 任务陈国金 判题机架构设计凌枫 整合代码编辑器陈卓恒 更新题目界面部分完成谭立业 浏览题目页面部分完成廖俊龙 接口测试曾平凡 前端页面测试曾俊涛 判题服务薛秋昊 判题服务今天计划完成的工作成员 任务陈国金…

js原型链污染

js原型链污染 原理介绍 对于语句:object[a][b] = value 如果可以控制a、b、value的值,将a设置为__proto__,我们就可以给object对象的原型设置一个b属性,值为value。这样所有继承object对象原型的实例对象在本身不拥有b属性的情况下,都会拥有b属性,且值为value。 可以通过…

基于米尔NXP i.MX93开发板OpenCV的相机捕捉视频进行人脸检测

本篇测评由优秀测评者“eefocus_3914144”提供。 本文将介绍基于米尔电子MYD-LMX93开发板(米尔基于NXP i.MX93开发板)的基于OpenCV的人脸检测方案测试。 OpenCV提供了一个非常简单的接口,用于相机捕捉一个视频(我用的电脑内置摄像头)1、安装python3-opencvapt install pyth…

hbase-2.2.7分布式搭建文档(附详细操作步骤命令及相关操作截图)

hbase-2.2.7分布式搭建文档 一,搭建前准备 1.检查是否已经安装JDK 2.搭建hbase前需要先搭建好hadoop 3.检查zookeeper是否正常启动 #启动zookeeper(三台都要启动) zkServer.sh start#查看zookeeper状态(一个leader两个follower) zkServer.sh status4.到官网或国内镜像站下载hb…