1 条题解
-
0
题目大意
给定一个 的网格图,有障碍物(
#)和可通行区域(.),其中有 个建筑物位于可通行格子上。
在可通行格子间可以上下左右移动,但不能出界或进入障碍物。
在原野(非建筑物的可通行格子)上每走一格需要消耗 1 升水,建筑物处可以补满水。
要求回答 个询问:从建筑物 到 ,需要的水壶最小容量是多少(即路径上连续原野段的最大长度最小化)。
核心思路
-
问题转化
如果两个建筑物之间有一条路径,那么路径上可能会经过若干段原野,每段原野的长度就是该段需要的水量。
由于可以在建筑物处补满水,所以整条路径需要的水壶容量等于路径上相邻建筑物之间原野段长度的最大值。
进一步,我们要求所有可能路径中,这个最大段长的最小值。 -
建筑物间边权
考虑任意两个建筑物,它们之间的最短路径上,原野段的最大长度是多少?
这可以通过 多源 BFS 从所有建筑物出发,计算每个非障碍格子到最近建筑物的距离(即原野步数)。
然后,对于相邻的两个格子,如果它们分别属于不同的建筑物(或同一个建筑物),就可以在它们对应的建筑物之间建立一条边,边权为这两个格子到各自建筑物的距离之和 + 1(因为中间一步是原野)。
但更简单的方法是:在 BFS 过程中,当从建筑物 扩展遇到另一个建筑物 时,它们之间的边权就是当前扩展的步数(即原野段长度)。 -
最小生成树
这样我们得到了一个建筑物之间的无向图,边权表示两个建筑物之间路径的最大原野段长度。
为了最小化任意两点路径上的最大边权,我们构建这个图的 最小生成树(MST)。
在 MST 上,两点路径上的最大边权就是它们之间所需的最小水壶容量。 -
查询处理
构建 MST 后,问题变成:回答 个查询,求 MST 上两点路径上的最大边权。
这可以用 树上倍增 预处理每个节点向上 步的路径最大边权,然后求 LCA 的同时求出路径最大值。 -
注意点
- 如果两个建筑物在 BFS 过程中无法连通,则它们不在同一个连通块,输出 -1。
- 如果两个建筑物之间路径不经过原野(即相邻或在同一建筑物群),则输出 0。
- 多源 BFS 时,要记录每个格子是从哪个建筑物扩展到的,当遇到不同建筑物的格子时添加边。
算法步骤
- 多源 BFS 从所有建筑物出发,记录每个格子的最近建筑物编号和距离。
- 在 BFS 过程中,若扩展到的格子已被另一个建筑物访问过,则在这两个建筑物间添加边(边权 = 两方距离之和)。
- 对得到的边集跑 Kruskal 求 MST。
- 在 MST 上预处理 LCA 和路径最大值。
- 对每个查询,输出对应路径最大值,若不在同一连通块则输出 -1。
-
- 1
信息
- ID
- 4413
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者