当前位置: 首页 > 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.zskr.cn/news/6581.html

相关文章:

  • Ubuntu取消vim自动对齐
  • 中文医学基准测试题库数据集:28万条标准化JSON格式医师考试题目与临床案例分析,覆盖28个医学专业领域,用于医学AI模型训练、临床决策支持系统开发、医学知识问答系统构建、医学教育辅助工具优化
  • 函数计算的云上计费演进:从请求驱动到价值驱动,助力企业走向 AI 时代
  • Kubernetes概述与部署
  • 使用AI容器镜像部署Qwen大语言模型
  • 作业03
  • vs code运行Java遇到的输入问题
  • 关于数据跨境,你应该了解的合规难题有哪些?
  • 国内开发者如何选择代码管理平台?三大主流工具深度对比
  • 维保信息查询
  • 人工智能学习路线学习资料整理
  • 软件设计师知识点总结(2023)上
  • 【运维自动化-标准运维】各类全局变量使用说明(中)
  • OFDM 自适应功率与比特分配
  • 1380亿条微博全量数据集,可用于自然语言处理、情感分析、舆情分析、推荐系统、用户行为数据、商业智能、人工智能模型训练、中文文本数据、地理位置信息、时间序列分析、JSON格式、机器学习、文本挖掘等
  • 本土化技术平台的崛起:Gitee如何重塑中国开发者生态
  • 研究生化学英文题库数据集:300万条LaTeX格式AI训练资源,覆盖有机化学物理化学无机化学分析化学,用于智能评估系统、个性化学习平台、化学知识图谱构建、自动化工具开发、深度学习模型
  • 多重分形去趋势交叉相关性分析
  • WPF 容器尺寸行为总结
  • django对接drf-spectacular替代swagger
  • 可画
  • Symbol VBRK: Invalid data type u SAP 事务成功新号码获取到 但是提交后提示失败如何处理
  • ollama如何安装使用
  • 手把手教你实现C++高性能内存池,相比 malloc 性能提升7倍!
  • LDPC 码 BP 算法性能研究
  • 内外网文件传输方式有哪些:从传统方案到专业系统的全面解析!
  • 实用指南:DeerFlow 实践:华为IPD流程的评审智能体设计
  • py之补环境代理脚本
  • AUTOSAR的MPU内存保护
  • 国产传输软件解决方案厂商优选指南