P6628 丁香之路 题解
P6628 丁香之路 题解
题意:
有一个完全图,定义任意两点 \(i\) , \(j\) 间的距离为 \(|i-j|\) 。
给定完全图上的一些边和一个起点 \(s\) ,对于每一个 \(i\) 求从 \(s\) 出发,遍历所有给定的边,最终到 \(i\) 的最短距离。
一. 简化版本
不妨先思考一下简化版本:求从 \(s\) 出发 ,遍历所有给定的边,最终回到 \(s\) 的最短距离。
那么,你行走的就是一个回路。
我们可以这样继续化简:你可以在图上添加一些边,然后走一个欧拉回路,其中这个欧拉回路经过所有给定的边。

如图,原图的丁香花路是 \(4↔5,1↔2,2↔3\) ,然后你新增了两条红色的边,然后原图上就形成了一条欧拉回路。
欧拉回路的长度就是实际走的长度。
这有什么好处呢?
发现这样一定可以覆盖所有可能的行走路径。
比如,下图中红色行走路径对应的欧拉回路的新建边为绿色线段。

注意: 节点 \(4,2\) 之间新建了两条边
二. 欧拉回路
于是乎我们就可以去想一些欧拉回路的性质:
-
每个点的度数为偶数 。
-
图连通 。
步骤一:
因为要构成欧拉回路的必要条件是每个点度数为偶数,那么我们就先处理每个节点度数的奇偶性问题。
我们可以把度数为奇数的点给单独拿出来,注意到这样的点的个数一定是偶数。
所以两两配对建边,就可以把节点度数都变成偶数。
为了使总代价最小,那么建边的代价就需要最小。
那么显然肯定是把度数为奇数的点按编号排序,然后依次两个一组连边,如:

这样度数的问题就解决了。
步骤二:
现在来考虑图联通的问题:
经过上述步骤后,我们会得到若干个连通块,每个连通块内部都有一个欧拉回路。
欧拉回路告诉我们:回路上的任何一个点都可以遍历完连通块内的点,并最终回到自己。
那么我们只需将这些连通块以最小的代价连通起来就可以得到整个丁香花路的欧拉回路的最小长度 。

比如,当你用绿色线将三个连通块连接起来后,那么欧拉回路大概长右图这样。
也就是说连接段的距离会被计算两遍。
那么我们将 \(s\) 与步骤一后形成的连通块放在一起做一遍最小生成树就能求出从 \(s\) 出发然后回到 \(s\) 的最小代价。
具体的,我们将连通块内的点按照编号大小从小到大排序,那么就有边 \(id_1↔id_2,id_2↔id_3...\) 这些边足够使图连通,而选择其他边一定不会更优,所以不用考虑其他边。剩下的就是最小生成树的板子处理了。
但这样还不是最优的,原因是在步骤一中还可以继续优化:
我们在度数为奇数的点中连了一些边,设某条形如 \(u↔v\) ( \(u<v\) ),那么我们完全可以这样连边使得总代价不变:
这样,很明显这样过后各个含有丁香花边的连通块的大小更大,那么各个连通块中连边的选择就更多,其对应的最小生成树的大小也更小,整体答案更优。
扩展到一般情况:
这里有一个牛逼的做法:
设终点是 \(t\) ,那么我们钦定我们从 \(s\) 经过所有丁香花边走到 \(t\) ,然后从 \(t\) 直接走回到 \(s\) (实际不走)从而形成一条欧拉回路。
那么就变成和上一个问题完全一样的了。
也就是说,我们强制选择一条连接 \(s,t\) 的边但是不计入答案贡献(因为实际上不走),然后按照前面问题的做法去处理。

如,起点 \(1\) ,终点 \(7\) 。
那么强制连一条蓝色的边。
然后欧拉回路路径如左下图,实际路径如右下图。

浙公网安备 33010602011771号