细剖最短路【闲谈,权当是饭后杂文】

                            细剖最短路

我想这篇细剖最短路都是站在巨人的肩膀上说话的,所以我觉得通过此篇文章就想要提高自己对最短路算法的认识,还是不要抱太大希望(这几句向雨巨学习…)。写给自己,饭后杂文。

我想最开始还是,再去看看最短路算法原理吧
弱经常用的就是…spfa,而且各种切最短路(水题),噗,是啊,只能切最水的水题。然后真是挂了。PTA基础最短路挂,二级最短路挂,最短路转化挂…挂太多了…我也不是很想去挂了…

先讲spfa吧;
1. spfa为什么好?哪一点最好…在负权边,这时类似Dijkstra算法等便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图,可以判断负环)。
2. spfa的证明(重要):每次将点放入队尾,都是经过松弛操作达到的。换言之,每次的优化将会有某个点v的最短路径估计值d[v]变小。所以算法的执行会使d越来越小。我们假定图中不存在负权回路,所以每个结点都有最短路径值。因此,算法不会无限执行下去,随着d值的逐渐变小,直到到达最短路径值时,算法结束,这时的最短路径估计值就是对应结点的最短路径值。
3. 复杂度: O(km) m为边数 k一般为2或3,最坏情况下会退化到O(n2)在SPFA的论文中,证明是非常不严谨甚至错误的,事实上在bellman算法的论文中已有这方面的内容,所以国际上一般不承认SPFA算法。
这种东西为什么容易挂呢,就是不稳定。。。在切水题的时候随便high,还有切非常爆炸大的图里面,用spfa。
实际的应用中SPFA的算法时间效率不是很稳定,为了避免最坏情况的出现,通常使用效率更加稳定的Dijkstra算法。

Dijkstra算法:
这是自己最不想用的算法,所以这个排斥,bellman太垃圾,就不由自主喜欢spfa了。今天摸起dij还真是有点感慨啊。对这个算法提出者郑重道歉,实在是瞎了*眼。(qaq).

算法思想:
将图G中所有顶点V分为两个顶点集合Va和Vb。如果源点S到u的最短路径已经确定,则点u属于集合Va, 否则就是Vb。最开始的时候只有源点属于Va,其余为Vb。算法结束的时候不要觉得所有的点都属于Va,懂得话其实都知道与源点相连的属于Va,其余属于Vb。可以在求最短路径的时候顺便记录最短路径…这个也是我要在后面说的…其实这两个算法思想讲完,基本上后面的都是小儿科,都是在思想上的延伸qaq…
算法效率:O(n^2).或者加个优先队列优化一下,这样只要图不是特别大就无敌了吧。其实无敌的是自己。。。真的。。。接下来的在算法里面的操作才是自己无敌,真无敌。

补几个基础题
Hdoj3790
题意:
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
思路:
只是要注意每条边都有距离和花费两种权,当且仅当两条边的距离相等时才比较花费。因为需要考虑两种权,所以算法代码只要改变一点点就好了。(这题还有重边,题目没有重边就是有重边)。
【不贴代码,自己思考啊,思考的魅力是无穷的(站着可以思考,坐着可以思考,睡觉更加可以思考了)】

然后举个伪反例(主要是题目意思和目的本来就是不同的)。
题意:
给出n个城市,然后给出m条单向路,给出了每条路的距离和花费,问一个人有k coins,在不超过money的情况下从1到n最短路径路径。
思路:
我相信很多人在上面那道题的影响下,肯定会想想,在保证最短路的前提下维护下最小花费?还是保证最小花费下维护一个最短路?这样两个想法的bug都非常明显啊。第一个,那是大错特错了,人家首要给你的条件满足<=k,你还抱住最短路长度不放,给你wa是同情。第二个,有个bug就是他是最小花费,可能存在一条路的花费大于最小花费但是他的路长度才是最短路,给你wa也不冤啊。
正解:
把满足<=k的那些点扔进优先队列里去,他们都可能是最短路的组成成份啊,出队去松弛一下,不断的进队出队。然后优先队列保证的是当花费不超过k的情况下优先让距离最近的点出队,可以避免上面“花费较大但是是最短路”的现象,这样优先的话,嗯,对吧qaq,不想解释了。然后这波操作看起来很简单的,但是真要动起来,对于萌新来说还是比较困难的。

插一句:本来最短路的思想就是贪心(还是DP)的嘛。

最短路记录路径:
Hdoj1385;
还是在最短路里面操作。
应该是开一个数组记录一下,在更新的时候记录。用一个pre数组记录路径。pre[i][j] 代表从起点i到终点j的最开始遇到的点。初始化pre[i][j]为j,然后在最短路更新的时候更新这个pre数组。

二级最短路:
(其实我也不是很懂为什么叫二级最短路,我觉得应该叫最短路拓展,嘻嘻~)
强行加一篇:http://www.wonter.net/?p=205 (wonter巨不会怪我吧)
比如求一个最短路径的最少数量或者最长数量,可以手动多加一个权值,每条有的边就是1,然后更新的时候更新,还有就是有种情况是等于的时候,就是有多种方式达到这个点,但是你要记录的是较小/大的那个。Hdoj3790也是这个道理。

posted @ 2016-07-20 23:09  see_you_later  阅读(156)  评论(0编辑  收藏  举报