【题解】【Dijkstra】Leetcode-2699-修改图中的边权
本文最后更新于:2023年6月12日 晚上 18:44
力扣2699题题解。

参考了灵神的题解,但感觉对于第二次Dijkstra的正确性有点模糊,重新整理了一下思路。
(以下将所有权值为-1的边视作【可修改边】) #### 第一次Dijkstra:
先将所有为-1(【可修改边】)的边看作1,以求得理论最小路径。
获得 source 到所有点的距离 dist1[] ,以及最短路径 minDist1 = dist1[destination]
判断结果:
若 minDist1 > target,则无解。返回空数组。
若 minDist1 == target,则成功,返回当前全部-1修改为1的边集。
若 minDist1 < target,则可能可以通过增大一些【可修改边】的值(目前为最小的1),使得最短路径增大。进行第二次Dijkstra。
(但也可能把所有【可修改边】都增大后最短路径依然不变,因为此时 minDist1 上没有【可修改边】)
第二次Dijkstra:
修改第一次最短路径上的【可修改边】,使得这条路径的权值和为target。
同时将其他【可修改边】的权值调的够大,使之不会影响到第二次最短路径为第一次最短路径。
获得 source 到所有点的距离 dist2[],以及最短路径 minDist2 = dist2[destination]
如果遇到【可修改边】的情况,则进行增大,增大策略如下:
增大策略(其中Dijkstra是正在检查节点x,然后检查到了【可修改边x-y】):
source - x - y - destination 这是可能成为最短路径的路径
要成为最短路径target,需满足 dist2[x] + W + E[y,destination] == target
其中:
dist2[x] 为第二次Dijkstra所获得的 source 到 x 最短距离的准确值
W 为【可修改边x-y】应该要修改成的值
E[y,destination] 为 y 到 destination 的最短距离的不准确值,E[y,destination] == minDist1 - dist1[y]
情况判断:
如果y在第一次的最短路径上:
- minDist1 == 起点到y的最短距离dist1[y] + y到终点的最短距离
- E[y,destination] == y 到终点的最短距离 == minDist1 - 起点到y的最短距离dist1[y]
如果y不在第一次的最短路径上:
minDist1 < 起点到y的最短距离 + y到终点的最短距离
E[y,destination] == y 到终点的最短距离 < minDist1 - 起点到y的最短距离dist1[y]
此时会把W修改得过大,使得经过这条边的最短路径大于target,但正因为这样,它不会影响到第一次的最短路径。
我们必须找到第一次最短路径上的【可修改边】并合理增大它的权值,使得这条路径权值和为target。
如果第一次最短路径上没有【可修改边】,即使增大了其他路径上的【可修改边】,最短路径也不会变化,依然是第一次最短路径,此时minDist2 < target无解。
最终我们把最短路径上的【可修改边】修改为合理值,并把其他路径上的【可修改边】的值改得过大,避免影响到最短路径。
判断结果:
- 若 minDist2 == target,则成功,返回修改权值后的边集。
- 若 minDist2 < target,则无解。(第一次最短路径上没有【可修改边】)返回空数组。
- 不存在 minDist2 > target 的情况。
时间复杂度: O((|V|+|E|)*log|E|)
空间复杂度: O(n^2)
我自己按照思路写的比较粗略的C++代码如下,或许改为朴素版还有优化的空间:
1 |
|
