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\}\), 铁路公司将票价定为:

\[\sum_{i=1}^k w_{e_i} - \max_{1 \leq i \leq k} w_{e_i} + \min_{1 \leq i \leq k} w_{e_i} \]

显然, 现在的票价不会比降价之前的贵.

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);
}
posted @ 2025-03-24 11:54  Steven1013  阅读(10)  评论(0)    收藏  举报