1 条题解
-
0
「SHOI2008」堵塞的交通 题解
问题重述
有一个 的网格图,每个格子是一个城市,相邻城市之间有道路连接。系统支持三种操作:
- Open:开通某条相邻城市之间的道路
- Close:关闭某条相邻城市之间的道路
- Ask:询问两个城市是否连通
所有操作总数不超过 ,。
算法思路
核心挑战
这是一个动态图连通性问题,需要支持边的动态添加和删除,同时回答连通性查询。直接使用并查集无法处理删边操作。
线段树分治
本题采用线段树分治来解决动态连通性问题:
- 将时间轴(询问顺序)作为线段树的区间
- 每条边的存在时间是一个区间 ,表示在第 个操作时开通,在第 个操作时关闭
- 将边插入到线段树覆盖其存在区间的所有节点中
可撤销并查集
- 在递归处理线段树时,将当前节点内的所有边加入并查集
- 递归结束后,需要撤销这些操作,保持并查集状态的一致性
- 使用按秩合并的可撤销并查集:
- 记录每次合并操作的细节
- 递归返回时,按栈顺序撤销合并操作
算法流程
预处理阶段
- 为每个网格点分配唯一编号
- 处理所有操作:
- Open操作:记录边的开通时间,初始化关闭时间为无穷大(到最后一个询问)
- Close操作:找到对应的Open记录,设置其关闭时间为当前时间
- Ask操作:记录询问的时间点和查询的两个点
线段树分治主算法
- 构建时间轴的线段树
- 递归处理每个时间区间:
- 将存在于当前时间区间的所有边加入并查集
- 如果到达叶子节点(对应一个Ask操作),回答查询
- 递归处理左右子区间
- 撤销当前节点的边合并操作
数据结构设计
边的表示
struct edge { int from, ver; // 边的两个端点 int u, v; // 存在时间区间 [u, v] };可撤销并查集
fa[i]:父节点size[i]:集合大小(用于按秩合并)stk[]:操作栈,记录合并操作以便撤销
复杂度分析
- 时间复杂度:,其中 是操作数, 是点数
- 每条边最多被插入 个线段树节点
- 每个节点的并查集操作是 的
- 空间复杂度:
关键技巧
时间轴化
将边的动态变化转化为静态的时间区间,这是线段树分治的核心思想。
离线处理
所有操作需要先读入,预处理出每条边的存在时间区间,然后统一处理。
可撤销数据结构
需要支持高效的合并和撤销操作,按秩合并保证了复杂度。
算法总结
本题是一个经典的动态图连通性问题,通过线段树分治 + 可撤销并查集巧妙地解决了边动态添加删除的难题:
- 问题转化:将边的动态存在转化为静态时间区间
- 分治思想:在线段树上按时间分治,批量处理边
- 可撤销结构:使用带撤销的并查集维护连通性
- 离线处理:预处理所有操作,确定每条边的生命周期
这种解法具有普适性,可以用于解决多种动态图问题,如:
- 动态连通性
- 动态二分图判定
- 动态最小生成树等
难点突破
- 思维跳跃:将动态问题转化为静态时间区间需要一定的洞察力
- 实现细节:可撤销并查集的正确实现,特别是撤销顺序
- 数据结构配合:线段树与并查集的高效结合
- 输入处理:边的匹配(Open和Close配对)需要小心处理
这道题综合考察了离线处理、分治思想、可撤销数据结构等多个重要算法概念,是一道训练综合能力的优秀题目。
- 1
信息
- ID
- 5852
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者