题目大意
可恶,我们老师竟然把紫题放到了模拟赛里。
题目传送门
原题中题意说的很清楚了。
思路
转化问题
首先先新建两条边,使原题点到点的问题转化成边到边的问题。
可以连接一条从 \(0\) 到 \(1\),长度为 \(0\) 的边,设这条边为 \(0\) 号边。
还可以连接一条从 \(n\) 到 \(0\),长度为 \(0\) 的边,设这条边为 \(m+1\) 号边。
这样原题就变为了从 \(0\) 号边到 \(m+1\) 号边的最小代价。
化边为点
边到边的问题有一种常见做法:化边为点。
即把每条边看做一个点,将边与边之间连边,从起点边向终点边求最短路得到答案。
这道题也可以这么做,可以将首尾相连的两条边相连(即两条边有共同的节点),边权为两条边长度的最大值(原题中的代价)。
优化建图
但这样有个很明显的缺点,如果原图是菊花图,那么新图的边数最多可达到 \(m^2\) 级别,需要优化建图。
不难想到一种思路,先枚举每个共同节点,再用 \(sz\) 级别的边数建新边(\(sz\) 为这个点相邻的边数)。
这样可以做到让新图的总边数控制在 \(m\) 级别。
不难想到,可以对 \(i\) 这条点(原图上的边)新建一个辅助点 \(pre_i\)。
可以连一条 \(i\) 到 \(pre_i\) 的边,边权为原边边长,并可以连一条 \(pre_i\) 到 \(i\) 的边,边权为 \(0\)。
将 \(nodes\) 中的点按照长度从小到大排序(\(nodes\) 表示这个点相邻的边),连一条 \(pre_{node_{i+1}}\) 到 \(pre_{node_{i}}\) 的,边权为 \(0\) 的边(\(1\le i < sz\))。
这样原图中两条边通过 \(pre\) 辅助点连了一条边,边权为两条边长度的最大值。
由于需要建双向边,可以再新建一个辅助点 \(suf_i\),和 \(pre_i\) 同理连边,请读者自行思考。
后记
求管理员通过。
有几个需要注意的细节如下。
- 一条 \(u\) 到 \(v\) 的原图边,在枚举共同节点 \(u\) 和枚举共同节点 \(v\) 时都要各建两个节点 \(pre_i\) 和 \(suf_i\),也就是每条边一共要新建 \(4\) 个节点。
- 十年 OI 一场空,不开 long long 见祖宗。
- 最终点数为 \(5m\),边数为 \(12m\),记得开够数组。
- 要使用 dijkstra,不要使用
死去的SPFA。