dij原来的写法请移步这里
首先,让我们举一个洛谷中的情境
这题中,我们可以二分mid答案,小于等于mid的边权是0,大于的是1,再计算最短路是否<=k;
那么在这样边权只有0和1的时候,dij算法是否可以优化呢?
可以
(不然我写这篇blog干嘛)
不必再使用优先队列,而只需要一个双段队列deque就可以解决
做法
做法就是一样每次取出队首,然后每次更新从它延伸出去的那条路权是1就放队尾,权是0就放队首
其他一毛一样
因为deque单次操作时间复杂度是O(1),能比优先队列省一个log,单次dij可以降到n的水平,非常优秀
而且这个法发不必边权是0和1,只要是0和大于0的数就行
当然,算法复杂度再好,前提都得是正确
证明
改用双端队列后,我们只需要证明这样入队仍能维护单调性即可
(因为大于0的任何数本质与1相同,为了方便证明就使用0和1了)
1:+0往前放
首先,假设目前队首是队伍中的min
那么取出队首加0后,仍是min,显然在队列中不会破坏单调性
2:+1往后放
第一步很好证,但+1后的min+1一定是最大值吗?
我们可以用反证法
假设队列中有一个min+2,使min+1破坏了单调性
我们向它提出一个疫情以来最常见的问候语:
你从哪里来的?
学过高等数学的朋友应该知道:
1+1=2
所以一定是从一个min+1再+1得来
但是此时队首还是min
第一步已经从队首的方向证明了单调性,不可能min+1比min先到队首
自相矛盾,假设错误
所以往后放也可以保证单调性
写完嘞,谢谢观看!!!
(还有问题可以评论走哦~~~)