2025.03.21 CW 模拟赛 B. 秋游
B. 秋游
原题链接.
题意
Sumny Bunny 迎来了学校的秋季出游活动, 他决定乘坐火车旅行.
Sumny Bunny 所在的区域有 \(n\) 个参观地点, 有 \(m\) 条双向铁路连接着这 \(n\) 个参观地点. 保证从任何一个参观地点出发, 经由铁路可以到达其余任何一个参观地点. 对参观地点和铁路编号后, 第 \(i\) 条铁路连接了地点 \(u_i\) 和地点 \(v_i\), 乘坐火车经过该铁路的花费为 \(w_i\).
铁路公司目前正在举行降价活动. 对于一种乘坐火车的路线 \(\{p_0, e_1, p_1, e_2, p_2, e_3, \ldots, e_{k-1}, p_{k-1}, e_k, p_k\}\), 铁路公司将票价定为:
显然, 现在的票价不会比降价之前的贵.
Sumny Bunny 的学校在参观地点 1 的附近, 因此他需要在那里开始乘坐火车. 他希望知道, 从地点 1 出发, 只按照一条完整的路线乘火车 (也即中途不下车), 到达其余每个地点的最小票价是多少?
思路
原限制比较严格, 我们考虑放宽限制
- 对于任意一条路径, 我们可以选择任意一个边权翻一倍, 任意一个边权置为 0.
可以发现, 对于该条件, 每一条路径的最小权值即为原限制所求. 因为我们一定会选择一个最小的边权翻一倍, 再将最大的边权置 0.
这样, 我们就可以考虑构建分层图了. 我们将原图分为 4 层, 每层都正常连边.
不妨设当前边的权值为 \(w\), 其连接了 \(u, v\) 两点.
那么我们可以从第一层的 \(u\) 向第三层的 \(v\) 连一条权值为 \(2w\) 的边, 表示将当前边的权值翻一倍, 同理, 我们也在第二层的 \(u\) 向第四层的 \(v\) 连一条权值为 \(2w\) 的边.
对于任意一条边权值置 0 的条件, 我们在第一层的 \(u\) 和第二层的 \(v\) 之间连边, 在第三层的 \(u\) 和第四层的 \(v\) 之间连边即可.
这样, 我们到第四层的路径一定会经过一条翻倍的边和一条置 0 的边, 满足条件.
连边部分代码.
void add(int u, int v, int w) {
e[getx(u, 0)].emplace_back(getx(v, 0), w);
e[getx(u, 0)].emplace_back(getx(v, 3), w);
e[getx(u, 1)].emplace_back(getx(v, 1), w);
e[getx(u, 2)].emplace_back(getx(v, 2), w);
e[getx(u, 3)].emplace_back(getx(v, 3), w);
e[getx(u, 0)].emplace_back(getx(v, 1), 0);
e[getx(u, 2)].emplace_back(getx(v, 3), 0);
e[getx(u, 0)].emplace_back(getx(v, 2), w * 2);
e[getx(u, 1)].emplace_back(getx(v, 3), w * 2);
}

浙公网安备 33010602011771号