开车旅行
![](https://img-blog.csdnimg.cn/20190801184829204.PNG)
![](https://img-blog.csdnimg.cn/20190801184838720.PNG)
最初想法
跑一次 Floyed, 把加油站独自提出来建一棵树, 跑最小瓶颈路, 时间复杂度 O(N3) .
实际上 上方的 Floyed 可以换成 N 次 Dijstra 的, 时间复杂度 O(N2) .
正解部分
与上方差不多的思路, 只不过优化了 建树过程 .
先说做法:
跑 Dijstra 时, 将所有加油站作为起点, 同时推入 优先队列, 跑最短路, 可以以 O(NlogN) 的复杂度得到 普通点离得最近的加油站编号 .
然后可以遍历每条边, 若两个端点离得最近的加油站不同, 则在两个加油站之间连一条经过两个端点的路径 .
最后求出最小生成树, 其余同上 .
为什么这样做 ?
考虑从加油站 x 出发可行的路线, 肯定是走最短路径到达另一个加油站 y .
若 x 到 y 路径上存在一条边 (u,v,w) 满足距离 u 最近的加油站为 x 且距离 v 最近的加油站为 y, 那么我们会将 (x,y,dist(x,y)) 加入生成树 .
否则可以证明 x 到 y 的路径不可能在最小生成树中出现:
-
找到一条边 (u,v,w), 设距离 u 最近的加油站为 a, 距离 v 最近的加油站为 b, u距离 x 近,v 距离 y 近 .
-
由条件可得 dist(a,u)≤dist(x,u), dist(b,v)≤dist(y,v).
-
因为
dist(a,b)=dist(a,u)+dist(v,b)+w≤dist(x,b)=dist(x,u)+dist(v,b)+w
dist(a,y)=dist(a,u)+dist(v,y)+w≤dits(x,y)=dist(x,u)+dist(v,y)+w
-
所以从 x 到 y 不会 比
从 x 到 b 再 从b 到 a 最后从 a 到 y 更优 .
![](https://img-blog.csdnimg.cn/2019080119314721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1picjE2Mg==,size_16,color_FFFFFF,t_70)
以上证明来自 wjz 的 ppt
实现部分
略 .