1 条题解
-
0
一、题意理解
我们有 个城市, 条铁路线(铁路线是链状的),每条铁路线依次经过若干城市,并给出相邻两个城市之间的行车时间。
每条铁路线上的边是单向的。
你从城市 出发,到达城市 ,可以在同一个城市换乘不同线路。目标:
- 找到最少花费时间的路线。
- 在满足最少时间的前提下,使得路径上所有相邻两城市之间的行车时间的平方和尽可能大。
注意:“相邻两个城市”指的是在换乘后的路径中相邻的两个城市(不是地理上相邻,而是你在旅行中连续经过的两个城市)。
例如:在一条线路上坐几站,再换乘另一条线路,那么换乘点的前后两段行车时间会被分别计入平方和。
二、模型转化
1. 最短路图 DAG
首先,我们要找到从 1 到 n 的所有最短路对应的路径。
这些路径构成一个 最短路 DAG:只要边 满足 ,则这条边在最短路 DAG 上。2. 关键:拆“颜色链”
原题中“铁路线”在最短路径 DAG 中可能只被部分使用。
如果我们把同一条铁路线上连续出现在最短路 DAG 中的边看作一个颜色块(称为trans_color),那么在一条颜色块内部,我们不能换乘,只能一直坐下去。
只有颜色块的分界点(即铁路线中某条边不在最短路 DAG 中)才会形成换乘机会,或者铁路线起点/终点也是一种边界。为什么这样做?
因为对于同一条铁路线且连续在最短路上的一段,我们是连续乘坐的,这些边的行车时间在最终路径上也是连续的。
对平方和来说,这一整段的时间之和是该段的时间长度,平方和是该段内每段小边的平方和累加。
当我们在不同颜色块之间换乘时,两个颜色块的最后一小段时间 和第一小段时间 之间就会产生 的贡献。3. 目标函数
假设我们得到了一条最短路径:
$$1 = v_0 \xrightarrow{t_1} v_1 \xrightarrow{t_2} v_2 \cdots \xrightarrow{t_k} v_k = n $$每个 是某条铁路线上的一小段的时间。
我们要最大化:且 是固定的(等于最短时间 )。
但这并不是对整体求平方和,而是对相邻两个城市之间的每一小段时间求平方和。
如果我们把同一颜色块的边合并在一起考虑,设一个颜色块内部的时间段为 ,
其平方和贡献为 。
对两个不同颜色块,在换乘时,它们的连接点的时间 和 在两个不同块中,它们的平方 和 分别属于各自块的贡献。为了统一,我们定义:对于一个颜色块 ,它内部连续时间的平方和是固定的(因为时间固定的情况下,平方和只依赖于每小段时间,而最短路 DAG 中这些时间固定)。
唯一要决定的是:我们在哪个城市换乘到该颜色块,以及从哪个城市离开该颜色块,这些决策会影响该颜色块的起始城市和结束城市,从而影响路径的时间划分和平方和。
四、代码实现框架
你的代码分为三大模块:
1. Dijkstra 模块(
dij::solve)- 用所有原始边建图跑 Dijkstra,得到 。
- 重新建图:只保留最短路 DAG 上的边()。
- 同时给同一条铁路线上且连续在最短路 DAG 中的边分配相同的
trans_color。这样形成若干个颜色链。
2. 拓扑排序(
topo::solve)- 在最短路 DAG 上拓扑排序,保证 DP 时无后效性。
- 对于每个城市 ,记录经过它的所有颜色链编号(
color[u]是它所在的所有颜色链的集合,去重后)。 - 之所以一个城市可能在多个颜色链中,是因为不同的铁路线经过它。
3. 李超线段树 DP(
lichao::solve)这里是最关键的部分:
状态定义
:从 到 走最短路,且在 结束当前颜色块时的最大平方和。
转移
当我们到达 ,且 在某个颜色链 上时,我们可能:
- 从同一条颜色链 的前一个城市 直接过来(不换乘),此时 可从 加上 转移。
- 在 处换乘到颜色链 ,此时需要找到上一个颜色链的结束点 ( 与 不同链),则从 加上新颜色链的第一段时间的平方(这里第一段时间是 吗?注意 到 必须有一条最短路 DAG 边,且 是颜色链 的起点)。
但实际上,代码里采用了一种更统一的方法:
对于每个颜色链 ,维护一个李超线段树(横坐标是 ,纵坐标是 加上某些调整项),当我们到达 时:
- 查询该颜色链 内所有可能的 ( 在横坐标轴上)的最大值 之类的东西。
- 这个查询的形式是 的最大值。
展开:
$$f[v] + (dis[u] - dis[v])^2 = f[v] + dis[u]^2 - 2\cdot dis[u]\cdot dis[v] + dis[v]^2 $$把 看作 ,那么对于每个 有一条直线:
在 处求最大值。
所以,对于每个颜色链,我们维护一个李超线段树,里面插入了该链上所有点 对应的直线。
查询时,对于 所在的颜色链 ,查询在 处的最大值 ,那么:
因为 已经包含了 的最大值,再加上 就得到 的最大值。
插入新直线
当我们求出 后,对于 所在的所有颜色链 ,插入直线:
表示 可以作为新的起点供后面的点查询。
五、算法复杂度
- Dijkstra:
- 拓扑排序与建图:
- 李超线段树:每个点会在它所属的每个颜色链中查询一次、插入一次,每个点所属颜色链数很少(最多为经过它的铁路线条数),总复杂度
空间 。
六、总结
这道题的核心在于:
- 最短路 DAG 的建立与颜色链划分。
- 将平方和最大化转化为每个换乘点的平方贡献独立,用 DP 优化。
- 使用李超线段树在颜色链维度维护一次函数最大值,实现高效 DP 转移。
最终结果:输出 和 ,其中 是在 结束的最短路的最大平方和。
如果你需要,我可以进一步解释李超线段树在这里如何帮助优化转移,或者画出更具体的转移图。
- 1
信息
- ID
- 6061
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者