最短路的基本三个算法为:SPFA,Dijkstra,FLoyd
(三道中文题就是这三个算法的裸体加上算法介绍已经算法正确性(不能严格证明但有帮助理解)…,尽量先刷三道中文裸体如果你不会这三种最短路算法)
三种最短路算法都很好理解,基本写法自行了解;
Floyd算法一般用于点的个数不多于200的题目,该算法时间复杂度为 V^3 ,Floyd 算法跑出的答案是多源最短路很少用在这次VJ里只有那道裸体需要用其他时候都不需要用,具体要用的时候一般问题都直接或间接涉及到要你求出所有点对最短路径或其他信息.
Dijkstra: 不用堆优化的dijkstra算法复杂度为V^2,用堆优化加邻接表的dijkstra复杂度为V*logE(尽量考虑写堆优化的dijkstra)
(该算法属于加点法,外层循环为点的个数,注意点数量的规模,太大的时候就考虑不要用dijkstra算法)
SPFA: 算法复杂度为KE,K是一个期望值(最差的时候为V,期望值是2);SPFA比较好写而且复杂度低于很多时候用堆优化的dijkstra,用途更广泛:判断正负环,跑有负权的最短路。可以跑 边数百万的图。(据了解容易被出题人卡数据,但还是很好用(可以跑负权图),写法有DFS BFS,栈 等等)
有兴趣的话可以了解一下最短路算法的正确性证明。
简要介绍各题基本思路:
A题:A题问的是过去和回来的最短路,因为是单向边,所以你要跑两遍最短路算法才能跑出来答案(可以以起点为原点,松弛的方式变一下一个是从起点出发到各点的最短路,一个是以起点为终点各点到起点的最短路,也可以分别跑起点到各点最短路和终点到各点最短路)。
B题:B题是一个判断正环的问题,用SPFA的DFS写法,从起点出发不断沿使点权增大的边走,看能否走到一个访问过两次的点。这里每个点的点权初始化就不太一样了(除起点外其他点权初始化为0),其次这里要求一定要从某个固定起点出发找到正环(题目说他一开始只有一种货币)
C题:判断负环,这题只要找到一个负环就OK,还有一个关于点权初始化的问题,建议可以百度了解一下。可以初始化所有点权为0,然后枚举各点作为起点跑DFS(只跑负边权),只要能跑到一个负环就输出YES.也可以用BFS跑,一个点入队超过N次 ( 了解BF的话其实是松弛超过N次,入队N次和松弛N次还是有差别的 )就说明存在负环(最短路径树最多N层,SPFA每松弛一轮会跑出一层)。也可以像跑最短路那样跑DFS(点权初始化为INFTY,起点初始化为0,沿着负边权跑(这种比全初始化为0的更慢)。)
D题:也是正环题而且没有要求从固定起点(有了B题的经验这题可以借鉴B题找正环的思路)
E题:超强的8000ms时限题,点数和边数都达百万(我觉得用堆优化的dijkstra可能会比SPFA更慢(V*logE+E) ),用SPFA可以跑出1900ms,这题也是要跑来回两趟,然后要求所有点点权之和。
F题:F题就是差分约束了,这题的差分约束条件是最短路性质,所以照常跑最短路(dijkstra我没跑,但是SPFA会被卡),SPFA在这里跑BFS会超时,可以跑堆优化的dijkstra,也可以跑栈的BFS跑最短路(直接跑堆优化的dijkstra吧)
G题:一道建图题,建图是关键,建好跑一遍最短路就过了。注意数组空间开大一点.
I题:我的思路是跑最大生成树.
K题:水题