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

UVa 11165 Galactic Travel

题目描述

银河系中有nnn颗行星上有人类定居点,编号从000n−1n-1n1。每个行星都有一个超空间跳跃门,理论上允许从任意行星UUU到任意其他行星VVV的跳跃。但由于技术原因,并非所有n(n−1)n(n-1)n(n1)种跳跃都是允许的,某些从UUUVVV的跳跃被禁止。题目以区间形式给出禁止跳跃:每行输入格式为U V1−V2U \ V1 - V2UV1V2,表示从行星UUU到行星V1,V1+1,…,V2V1, V1+1, \ldots, V2V1,V1+1,,V2(包含两端)的所有跳跃是被禁止的。

要求计算从起点SSS到终点TTT所需的最少跳跃次数,如果不可达则输出Impossible\texttt{Impossible}Impossible

题目分析

问题本质

这是一个无权图上的最短路径问题

  • 节点:nnn个行星,编号0…n−10 \ldots n-10n1
  • 边:理论上所有有序对(u,v)(u, v)(u,v)u≠vu \neq vu=v)都是允许的,但题目给出了某些从uuu到连续区间[V1,V2][V1, V2][V1,V2]的跳跃是被禁止的。因此,允许的边就是除了这些禁止边之外的所有边。
  • 目标:求从SSSTTT的最少步数。

数据规模

  • n≤100,000n \leq 100,000n100,000
  • k≤41,000k \leq 41,000k41,000(禁止区间的数量)
  • 禁止跳跃的总对数≤5,000,000\leq 5,000,0005,000,000

难点分析

  1. 图非常稠密:理论上完全图有约n2n^2n2条边,无法显式存储。
  2. 禁止边数量可能很大:虽然kkk不大,但每个禁止区间可能覆盖大量节点,总禁止边数可达5×1065 \times 10^65×106
  3. 需要快速找到可到达的节点:在 BFS 中,从当前节点uuu出发,需要知道哪些vvv是可以到达且未被访问过的。

关键观察

由于允许的边几乎就是全集(除了禁止区间),我们可以换个角度思考:

  • 维护一个集合unvisited\texttt{unvisited}unvisited,存放所有尚未被访问过的节点。
  • 当访问节点uuu时,我们想找到所有可以到达的vvv(即未被禁止且未被访问)。因为允许的边是除了禁止区间外的所有边,所以这些vvv就是unvisited\texttt{unvisited}unvisited集合中除去禁止区间后剩余的所有节点。

这样,BFS 的过程就变成了:

  • unvisited\texttt{unvisited}unvisited中取出所有可以到达的节点,将它们加入队列,并从unvisited\texttt{unvisited}unvisited中删除。
  • 问题转化为:如何高效地从有序集合中批量删除多个区间内的元素。

解题思路

数据结构选择

  1. 禁止区间存储:使用vector<vector<pair<int, int>>> forbidden(n)\texttt{vector<vector<pair<int, int>>> forbidden(n)}vector<vector<pair<int, int>>> forbidden(n),对于每个节点uuu,存储它的所有禁止区间[l,r][l, r][l,r]
  2. 未访问节点集合:使用set<int> unvisited\texttt{set<int> unvisited}set<int> unvisited,支持有序遍历和删除操作。
  3. BFS 队列:标准队列存储(节点,距离)(节点, 距离)(节点,距离)

算法步骤

  1. 初始化:将所有节点0…n−10 \ldots n-10n1插入unvisited\texttt{unvisited}unvisited集合。
  2. 起点处理:将SSSunvisited\texttt{unvisited}unvisited中删除,加入队列,距离为000
  3. BFS\texttt{BFS}BFS循环
    • 取出队首节点uuu和当前距离distdistdist
    • 如果u==Tu == Tu==T,返回distdistdist
    • 获取uuu的所有禁止区间列表ban\texttt{ban}ban
    • 遍历unvisited\texttt{unvisited}unvisited集合,跳过所有落在禁止区间内的节点,将剩余的节点收集到toVisit\texttt{toVisit}toVisit列表中。
    • 对于toVisit\texttt{toVisit}toVisit中的每个节点vvv
      • unvisited\texttt{unvisited}unvisited中删除vvv
      • (v,dist+1)(v, dist+1)(v,dist+1)加入队列。
  4. 结束:如果队列为空仍未找到TTT,返回Impossible\texttt{Impossible}Impossible

关键技巧

在遍历unvisited\texttt{unvisited}unvisited集合时,我们需要高效地跳过多个禁止区间。做法如下:

  • 使用迭代器it\texttt{it}it指向当前遍历位置。
  • 对每个禁止区间[l,r][l, r][l,r]
    • 找到第一个≥l\geq ll的节点位置,在此之前的所有节点都是可到达的,加入toVisit\texttt{toVisit}toVisit
    • 将迭代器移动到第一个>r> r>r的位置,即跳过整个禁止区间。
  • 处理完所有禁止区间后,将剩余的所有节点也加入toVisit\texttt{toVisit}toVisit

这样,每个节点只会被访问一次(加入toVisit\texttt{toVisit}toVisit一次),总复杂度为O((n+O((n +O((n+禁止区间总数)log⁡n)) \log n))logn),可以接受。

复杂度分析

  • 时间复杂度:O((n+∑∣banu∣)log⁡n)O((n + \sum |ban_u|) \log n)O((n+banu)logn),其中∑∣banu∣≤k\sum |ban_u| \leq kbanuk,最坏情况下约O((n+k)log⁡n)O((n + k) \log n)O((n+k)logn)
  • 空间复杂度:O(n+k)O(n + k)O(n+k)用于存储禁止区间和未访问集合。

代码实现

// Galactic Travel// UVa ID: 11165// Verdict: Accepted// Submission Date: 2026-02-25// UVa Run Time: 0.080s//// 版权所有(C)2026,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intsolve(intn,intk,vector<vector<pair<int,int>>>&forbidden,intS,intT){// 初始化未访问集合set<int>unvisited;for(inti=0;i<n;++i)unvisited.insert(i);// BFS 队列queue<pair<int,int>>q;// (node, dist)q.push({S,0});unvisited.erase(S);while(!q.empty()){intu=q.front().first;intdist=q.front().second;q.pop();if(u==T)returndist;// 获取当前节点 u 的禁止区间列表auto&ban=forbidden[u];vector<int>toVisit;// 遍历 unvisited 集合,跳过禁止区间autoit=unvisited.begin();for(auto&interval:ban){intl=interval.first,r=interval.second;// 找到第一个 >= l 的节点autoendIt=unvisited.upper_bound(r);// 收集 [it, 第一个禁止节点) 区间内的节点while(it!=unvisited.end()&&*it<l){toVisit.push_back(*it);++it;}// 跳过整个禁止区间 [l, r]it=endIt;}// 收集剩余的节点while(it!=unvisited.end()){toVisit.push_back(*it);++it;}// 将这些节点加入队列并从 unvisited 中删除for(intv:toVisit){unvisited.erase(v);q.push({v,dist+1});}}return-1;// 不可达}intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intN;cin>>N;for(intcaseNum=1;caseNum<=N;++caseNum){intn,k;cin>>n>>k;// 禁止区间列表,forbidden[u] 存储 u 的所有禁止区间 [l, r]vector<vector<pair<int,int>>>forbidden(n);for(inti=0;i<k;++i){intu,v1,v2;chardash;cin>>u>>v1>>dash>>v2;// 格式 "U V1-V2"forbidden[u].emplace_back(v1,v2);}intS,T;cin>>S>>T;intans=solve(n,k,forbidden,S,T);cout<<"Case #"<<caseNum<<": ";if(ans==-1)cout<<"Impossible\n";elsecout<<ans<<"\n";}return0;}

总结

本题的核心思想是利用集合维护未访问节点,通过跳过禁止区间来快速找到可到达节点。这种方法避免了显式建图,充分利用了允许边近乎全集的特性,在稠密图中也能高效运行。对于类似的大规模图上BFS\texttt{BFS}BFS问题,如果允许边远多于禁止边,这种逆向思维非常有用。

http://www.jsqmd.com/news/641301/

相关文章:

  • 【限时解密】SITS2026多模态预训练权重初始化协议:3步规避模态坍缩,附可运行PyTorch模板
  • AO3镜像站终极指南:7个关键步骤轻松访问全球最大同人创作平台
  • 千问3.5-2B在内容审核场景:UGC图片敏感主体识别与文字合规初筛
  • 【原创】IgH EtherCAT主站详解(一)--EtherCAT协议、帧格式和ESC
  • [具身智能-360]:部署和调用大语言模型主要有两种路径:云服务API调用和私有化部署。
  • 别再为UniApp和WebView通信发愁了!一个真实项目中的消息传递实战(附完整SDK配置流程)
  • MySL优化全攻略:索引、SL与分库分表的最佳实践
  • Linux内存管理全解析:从原理到实践,让你的服务器不再“内存不足”
  • 混合有源滤波器(HAPF)的MATLAB-Simulink仿真及补偿前后系统谐波对比
  • OpenClaw进阶实战(十三):电商比价工作流(二)——智能比价与动态调价
  • TGRS 2026 即插即用 | 注意力篇 | HEWL:小波上采样,通道-空间-频域交互联合高频增强,细节全保留!
  • K8s Ingress实战:从零配置Nginx Ingress Controller,实现基于路径和域名的灵活路由
  • 卫星通信是利用地球同步卫星作为中继站转发微波信号,实现地面站之间远距离通信的技术
  • ZYNQ中断编程避坑指南:从定时器中断看GIC配置与常见错误排查
  • ST7789显示屏终极指南:用STM32硬件SPI实现快速DMA驱动的完整方案
  • 如何永久保存您的微信聊天记录?WeChatExporter完整备份方案详解
  • 避开JDK8 Stream流的这些坑:filter/map/collect的7个易错点详解
  • 2026届学术党必备的五大AI科研工具实际效果
  • 机器学习工程师的瓶颈突破:高需求领域清单
  • day1 Vue学习
  • 实战指南:Intel I350系列网卡PXE功能精准配置与状态诊断
  • Windows热键冲突终极解决方案:3分钟快速定位占用程序的完整指南
  • Hermes-Agent 新手安装指南(言简意赅版)
  • MacPort vs Homebrew:实测PHP安装速度对比及多版本管理技巧(附避坑指南)
  • 保姆级教程:手把手教你用CANoe/LINalyzer分析LIN诊断报文(附PDU结构拆解)
  • posting替换postman(好像还是不太好用)
  • 艾尔登法环存档迁移终极指南:如何用 EldenRingSaveCopier 安全备份和转移你的角色
  • 从零上手MCP:手把手教你搭建第一个AI工具箱
  • 腾讯云轻量服务器新用户避坑指南:从宝塔面板到Docker环境,我的30天免费体验全记录
  • 多模态情感分析不再“黑盒”:SITS2026开源可解释性工具包(含Grad-CAMv3+Attention Gate可视化模块)