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

LOJ #3835. 「IOI2022」千岛 题解

Description

千岛是爪哇海里一组美丽的岛屿,其中有 \(N\) 个岛屿,编号为从 \(0\)\(N - 1\)

\(M\) 艘独木舟在岛屿之间航行,编号为从 \(0\)\(M - 1\)。对于满足 \(0 \le i \le M - 1\) 的所有 \(i\),独木舟 \(i\) 可以停靠在岛屿 \(U_i\)\(V_i\),并且在岛屿 \(U_i\)\(V_i\) 之间航行。具体来说,当独木舟停靠在岛屿 \(U_i\) 时,可以用它从岛屿 \(U_i\) 去往岛屿 \(V_i\),此后该独木舟就变成停靠在岛屿 \(V[i]\)。类似地,当该独木舟停靠在岛屿 \(V[i]\) 时,它可以从岛屿 \(V_i\) 航向岛屿 \(U_i\),此后该独木舟就变成停靠在岛屿 \(U_i\)。在初始时,该独木舟停靠在岛屿 \(U_i\)。可能有多艘独木舟能用于在同一对岛屿之间航行。也可能会有多艘独木舟停靠在同一个岛屿处。

出于安全考虑,各艘独木舟在每次航行后必须进行维修,因此同一独木舟不允许紧接着完成两次航行。也就是说,在用完某艘独木舟 \(i\) 后,必须先用过另外某艘独木舟,才能再启用独木舟 \(i\)

Bu Dengklek 想策划一次在部分岛屿之间的旅行。她的旅程是合理的,当且仅当满足如下条件:

  • 她的旅程应从岛屿 \(0\) 开始,并且在该岛屿结束。
  • 她应该游览岛屿 \(0\) 之外的至少一个岛屿。
  • 在旅行结束后,每艘独木舟应停靠在旅行开始前它所在的岛屿。也就是说,对于满足 \(0 \le i \le M - 1\) 的所有 \(i\),独木舟必须停靠在岛屿 \(U_i\)

请你帮助 Bu Dengklek 找出包括至多航行 \(2\;000\;000\) 次的合理旅行,或者告诉她不存在合理旅行。
可以证明,在本题所给出的约束条件下(参见约束条件部分),如果存在合理旅行,则必然存在航行次数不超过 \(2\;000\;000\) 次的合理旅行。

\(N\leq 10^5,M\leq 2\times 10^5\)

Solution

首先直接是不好构造的,考虑删点。

容易发现出度为 \(0\) 的点一定不能被经过,所以可以把这些点删掉,删掉后可能会生成新的出度为 \(0\) 的点,用拓扑排序的东西维护即可。

现在每个点的出度都至少是 \(1\) 了。如果起点 \(0\) 的出度为 \(1\),则在走的过程中不能经过 \(0\),可以把 \(0\) 删掉,并把起点 \(s\) 设为 \(nxt_0\)

可以证明只要当前的 \(s\) 出度大于等于 \(2\) 则一定有解。设 \(v_1\)\(s\) 第一个出边的终点,\(v_2\) 是第二个出边的终点。

如果 \(v_1\)\(v_2\) 一起走可以走到同一个点 \(x\),则可以构造成 \(s\) 先沿着 \(v_1\) 走到 \(x\),再在 \(x\) 这里走一个环,然后走回 \(v_1\)\(s\)。对 \(v_2\) 做同样的事情。(注意这里走的过程是需要动态改变边的方向的)

如果走不到同一个点,那么两个点可以走到不同的环,则 \(s\)\(v_1\) 再走环回到 \(v_1\)\(s\),再走 \(v_2\) 的环,然后走 \(v_1\) 的环,再走 \(v_2\) 的环即可。

直接分讨可能细节较多,这里有一个非常优美的写法是从 \(s\) 暴力 dfs,记录上一条走的边 \(lst\),每次枚举任意一条不是 \(lst\) 的出边走。如果当前时刻回到 \(s\) 且每条边都以达到初始状态就停止。经过手玩会发现这个写法刚好能囊括刚才的所有讨论,且细节大幅减少。

时间复杂度:\(O((N+M)\log N)\)

Code

#include "islands.h"
#include <bits/stdc++.h>const int kMaxN = 2e5 + 5;int n, m, s, cnt;
int op[kMaxN];
std::set<std::pair<int, int>> G[kMaxN], rG[kMaxN];
std::queue<int> q;
std::vector<int> vec;
bool del[kMaxN];void topo() {for (; !q.empty(); q.pop()) {int u = q.front();if (del[u]) continue;del[u] = 1;for (auto [v, id] : rG[u]) {if (del[v]) continue;G[v].erase({u, id});if (!G[v].size()) q.emplace(v);}}
}void dfs(int u, int lst) {if (u == s && !cnt && lst != -1) return;// std::cerr << u << ' ' << lst << ' ' << cnt << '\n';for (auto [v, id] : G[u]) {if (id == lst) continue;cnt += (!op[id] ? 1 : -1), op[id] ^= 1, vec.emplace_back(id);G[u].erase({v, id}), G[v].emplace(u, id);return dfs(v, id);}
}std::variant<bool, std::vector<int>> find_journey(int N, int M, std::vector<int> U, std::vector<int> V) {n = N, m = M;for (int i = 0; i < m; ++i) {op[i] = 0, G[U[i]].emplace(V[i], i), rG[V[i]].emplace(U[i], i);}for (int i = 0; i < n; ++i)if (!G[i].size())q.emplace(i);topo();// std::cerr << s << ' ' << G[s].size() << '\n';s = 0;std::vector<int> tmp;for (; G[s].size() == 1;) {auto [nxt, id] = *G[s].begin();// std::cerr << "shabi " << s << ' ' << nxt << ' ' << id << '\n';q.emplace(s), tmp.emplace_back(id), s = nxt;topo();}if (!G[s].size() || del[s]) return false;for (int i = 0; i < n; ++i) {for (; G[i].size() > (i == s) + 1; G[i].erase(G[i].begin())) {}}dfs(s, -1);std::vector<int> res = tmp;for (auto x : vec) res.emplace_back(x);std::reverse(tmp.begin(), tmp.end());for (auto x : tmp) res.emplace_back(x);// std::cerr << "??? " <<  tmp[0] << ' ' << res[0] << '\n';// for (auto x : res) std::cerr << x << ' ';// std::cerr << '\n';return res;
}
http://www.wxhsa.cn/company.asp?id=6509

相关文章:

  • (附源码)高校拼车管理系统的设计与实现 - 实践
  • Ubuntu取消vim自动对齐
  • AI产品测试学习路径全解析:从业务场景到代码实践
  • 代码随想录算法训练营第一天 | leetcode 704 27 977
  • 中文医学基准测试题库数据集:28万条标准化JSON格式医师考试题目与临床案例分析,覆盖28个医学专业领域,用于医学AI模型训练、临床决策支持系统开发、医学知识问答系统构建、医学教育辅助工具优化
  • 函数计算的云上计费演进:从请求驱动到价值驱动,助力企业走向 AI 时代
  • 【SPIE出版】第五届计算机图形学、人工智能与数据处理国际学术会议
  • 快速边缘块稀疏贝叶斯学习MATLAB实现
  • Kubernetes概述与部署
  • XXII Open Cup : Grand Prix of Southeastern Europe
  • GNSS终端授时方式
  • SpringAI接入DeepSeek大模型实现流式对话
  • 通知语音播报功能,解锁全新体验
  • 使用AI容器镜像部署Qwen大语言模型
  • 【IEEE冠名,香港中文大学(深圳)主办)第五届IEEE能源工程与电力系统国际学术会议(IEEE-EEPS 2025)
  • C#实现Access表格自增ID的重置
  • 运用深度学习模型实现图像的分类
  • 设备ONVIF接入平台EasyCVR私有化视频平台级联到海康平台目录丢失根因定位
  • java 通过模板输出word
  • 【设计模式】单例模式 - 实践
  • ubuntu服务器docker容器启动java项目
  • 【2025最新】企业信息模糊搜索API设计与实践指南
  • 一键搞定本土认证难题,AnalyticDB版Supabase助力AI应用实现支付宝微信登录
  • sumifs根据条件求和
  • ubuntu服务器docker安装部署ngix
  • c++右值引用和移动语义
  • 彩笔运维勇闯机器学习--梯度下降法
  • 作业03
  • 项目管理软件产业革命:从工具升级到生产力范式转移
  • vs code运行Java遇到的输入问题