当前位置: 首页 > news >正文

[CEOI 2025] theseus 做题记录

头皮发麻的题目。link

对于一道题目,我们需要观察题目的对象形式有什么特点。对于一道构造题,我们需要思考现在我们想要什么。

对于这题,观察到需要用到一个隐藏条件——点的编号,从编号信息入手。

  • Trial 1:对于一条边 \((u, v)\),根据 \(u,v\) 的大小关系以及边的 label 相当于确定该边的方向。

也就是说,我们给边进行 label 相当于给边进行定向。

注意到 travel 函数是我们自己设计的。为了避免随机化,我们可以固定每个点走的边。

  • Trial 2:为了避免随机游走,travel 的时候可以考虑走出边中编号最小的点。

进一步的,我们确定每个点下一步走到的点后,不难发现这形成了一棵树

这样我们就有了一个思考猜测:通过启发式合并来保证额外走的边数为 \(\mathcal O(\log n)\) 级别的。

先求出每个点的最短路,按照最短路长度分层。

对于某一层的每个点,对于其与上一层的点的连边,显然可以直接定向。

对于同一层内部的点,我们从小到大枚举每个点 \(u\),以及从小到大枚举其连接的点 \(v\),这样枚举的好处是无后效性。

如果 \(u\)\(v\) 已经有父亲了,那么我们可以定向:让有父亲的点连向另一个点。如果都没有父亲,考虑令子树较大的点作为子树较小的点的父亲。

这样就做完了。

点击查看代码
#include <bits/stdc++.h>
#define ll int
#define LL long long
#define uLL unsigned LL
#define fi first
#define se second
#define mkp make_pair
#define pir pair <ll, ll>
#define pb emplace_back
#define i128 __int128
const ll maxn = 10010, mod = 998244353, M = 14348907;
const LL inf = 1e18;
template <class T>
void rd(T &x) {char ch; ll f = 0;while(!isdigit(ch = getchar()))if(ch == '-') f = 1;x = ch - '0';while(isdigit(ch = getchar()))x = (x << 1) + (x << 3) + ch - '0';if(f) x = -x;
}
ll power(ll a, ll b = mod - 2, ll p = mod) {ll s = 1;while(b) {if(b & 1) s = 1ll * s * a % p;a = 1ll * a * a % p, b >>= 1;} return s;
}
template <class T1, class T2>
void add(T1 &x, const T2 y) { x = x + y >= mod? x + y - mod : x + y; }
template <class T1, class T2>
void sub(T1 &x, const T2 y) { x = x < y? x + mod - y : x - y; }
template <class T1, class T2>
ll pls(const T1 x, const T2 y) { return x + y >= mod? x + y - mod : x + y; }
template <class T1, class T2>
ll mus(const T1 x, const T2 y) { return x < y? x + mod - y : x - y; }
template <class T1, class T2>
void chkmax(T1 &x, const T2 y) { x = x < y? y : x; }
template <class T1, class T2>
void chkmin(T1 &x, const T2 y) { x = x < y? x : y; }
using namespace std;ll dis[maxn], q[maxn], l, r, siz[maxn], mn[maxn], d[maxn];
vector <pir> to[maxn]; vector <ll> vec[maxn];vector <ll> label(ll n, vector <pir> edge, ll t) {vector <ll> res(edge.size());for(ll i = 1; i <= n; i++) dis[i] = -1;q[l = r = 1] = t, dis[t] = 0;for(ll i = 0; i < edge.size(); i++) {ll u = edge[i].fi, v = edge[i].se;to[u].pb(mkp(v, i));to[v].pb(mkp(u, i));}while(l <= r) {ll u = q[l++];for(auto [v, id]: to[u])if(dis[v] == -1) {dis[v] = dis[u] + 1;q[++r] = v;}}for(ll u = 1; u <= n; u++) vec[dis[u]].pb(u), mn[u] = n + 1, siz[u] = 1;for(ll i = n; i; i--) {if(vec[i].empty()) continue;for(ll u: vec[i])for(auto [v, id]: to[u])if(dis[v] < dis[u]) res[id] = (u > v), chkmin(mn[u], v);sort(vec[i].begin(), vec[i].end());for(ll u: vec[i]) {sort(to[u].begin(), to[u].end());for(auto [v, id]: to[u])if(dis[v] == dis[u] && u < v) {if(!d[u] && v > mn[u]) siz[d[u] = mn[u]] += siz[u];if(!d[v] && u > mn[v]) siz[d[v] = mn[v]] += siz[v];if(d[u]) res[id] = 0;else if(d[v]) res[id] = 1;else {if(siz[u] <= siz[v]) res[id] = 0, siz[d[u] = v] += siz[u];else res[id] = 1, siz[d[v] = u] += siz[v];}}if(!d[u]) siz[d[u] = mn[u]] += siz[u];}}return res;
}ll travel(ll n, ll u, vector <pir> e) {ll p = n + 1;for(auto [v, w]: e)if((u < v) ^ w) chkmin(p, v);return p;
}
http://www.hskmm.com/?act=detail&tid=19117

相关文章:

  • 2025 年钣金加工厂家最新推荐排行榜发布:江门,珠三角钣金加工厂选择指南
  • 全文 -- Vortex: Extending the RISC-V ISA for GPGPU and 3D-Graphics Research - 指南
  • 2025.9.26 - 9.30
  • Codeforces Round 1053 (Div. 1) D. Attraction Theory
  • 通过AWS SSO设备代码认证进行AWS凭证钓鱼攻击(2024年更新)
  • 解码数据结构栈
  • 第七章 手写数字识别V4
  • 什么?你的蓝牙用不了了?
  • 模板库
  • 30.Linux DHCP 服务器 - 详解
  • [K230学习笔记] 前言
  • 集训队作业3——qoj#11723
  • 2025 年推拉门品牌推荐排行榜发布:聚焦玻璃推拉门,钛镁合金推拉门,厨房推拉门,阳台推拉门,淋浴隔断推拉门选择指南!
  • 2025.9.27比赛总结
  • [K230学习笔记] 目录
  • 116.飞行员兄弟
  • 2025系统门窗品牌推荐榜单发布,吉缘等一线品质品牌隔音节能实力解析
  • 课程总结(作业2)
  • 旅游管理虚拟仿真实训室:打通理论与实践壁垒 - 详解
  • 【光照】[PBR][漫反射]实现方法对比
  • Xpath 提取数据
  • Java异常以及处理
  • 复习计划
  • RTC
  • 卡特兰数与反射容斥
  • 题解:QOJ9619/洛谷13568 [CCPC 2024 重庆站] 乘积,欧拉函数,求和(数论+状压DP)
  • Momentum Gradient Descent(动量梯度下降)
  • README
  • Halcon算子——2D几何变换
  • 深入解析:深度解析 CUDA-QX 0.4 加速 QEC 与求解器库