【Roadblocks|次 短 路】P2865

这题呢很考验对最短路的理解;
连接不给了,题目标题和编号都在文章标题上;

必须清楚的了解各个算法的步骤,每个操作这么做的原因才能作出合理适当的改造;
求次短路和最短路还是有挺大区别的;
最短路这个玩意两种主要算法是DIJKSTRA和SPFA,这两种算法在求最短路的时候还是有比较大的区别的;
DIJKSTRA是用有限度列去更新;而SPFA是一次次的松弛;
但是这题求的是次短路,不是次短路;
为此DIJKSTRA的st或者说是vis数组就不能拿出来用了;
因此我们,对于每次寻找出来的寻找几条规律;
1.拿出最短路,发现这条边比最短路好;
2.拿出最短路,发现这条边比次短路好;
3.拿出次短路,发现这条边比次短路要好;

应该要注意这几种情况的优先顺序;这样子不仅能保证逻辑正确还能保证优化时间,虽然这题也用不了多少时间;

1.对于第一种情况来说,我们要先把最短路的值赋值给次短路,再把新找出来的边赋值给最短路;
2.我们可以直接更换次短路;
3.直接更换次短路;

这上面的操作与判断就是本题的核心;优先队列DIJKSTRA是可以做这个题的,你可以选择把vis数组给去掉,让你的DIJKSTRA长得和SPFA一样,其实DIJKSTRA把优先队列换成队列之后就是一个SPFA,这样子是不能够保证出队两次就可以得到正解的;
但是如果用优先队列DIJKSTRA,每次更新哪条边,就把哪条边给塞进优先队列里面,这样子做应该是比较标准或者说比较保险的;
然后每次出队的时候去更新;
这样子做我可以保证在两次VIS之内完成,实验数据测出来是这样的,绝对能过;首先最短路我就不证明了,这就是优先队列的证明一样的;

然后对于次短路来说,如果我要更新一条更长的次短路,因为优先队列那么比他小的次短路肯定已经更新过了;证明完毕,这就是数学归纳法;这也能够说明为什么两次VIS就够了;
这时不免再次感觉到DP和图论的关系,一个是在DAG里面,一个用DIJKSTRA和SPFA来找最优解;

我们可以想一下为什么去做次短路的时候,为什么可以只用最短路和次短路来更新,因为对于一条次短路,他肯定是由长度不为0的次短路,和剩下的最短路组成的,这一定就是次短路,如果不信就拿反证法来证明一下;

把洛谷上的题解的优先队列去掉改成普通队列之后,甚至会快得多;SPFA其实本质上就是按照一定的不离谱的顺序去一直松弛,松弛直到没有东西可以松弛,那时候就退出循环了,SPFA求三短路其实找这种逻辑来说也是可以的;

接下来考虑另一种情况,如果说不能同一条边走两次的话,那么spfa应该是不行的,因为他是属于松弛的做法,而不是像DIJKSTRA一样路径鲜明;所以我们应该要把每次更新后他的前驱给记录下来;
但是这样子只能保证不会重边但不能保证不重点;

代码如下:

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=200100;
typedef pair<int,int> PII;
int e
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值