最短路径经典题集

最短路径大体分为2种,单源最短路径和多对顶点之间的最短路径;

导论上一句话写的比较好:

边的权值还可以被解释为其他的某种度量标准,而不一定是距离。它常常被用来表示时间、费用,罚款,损失或者任何其他沿着一条路线性积累的和我们试图将其最小化的某个量;

最短路径还和dp有一定的关系;因为他符合最优子结构和公共子问题;

例如Floyd就是一种动归的解法;

常用的求最短路的算法是

Dijkstra算法

A*算法
SPFA算法
Bellman-Ford算法
Floyd-Warshall算法
Johnson算法
而各个算法的基本思想都是松弛,松弛是改变最短路径和前驱的唯一方式;

上面的算法之间的区别在于对每条边进行松弛操作的次数,以及对边执行松弛操作的次序有所不同;

各个算法各有千秋,另外还可以与优先队列,堆操作,队列等联系使用,可能效率更高;

具体分析见下面的poj关于最短路的题解:(后面的级别是针对新手说的,大牛可pass哈。。)

1.poj1062 昂贵的聘礼(中等)

此题是个经典题目;用Dijkstra即可;但是其中的等级处理需要一定的技巧;

要理解好那个等级制度;这个处理好,基本就是裸体Dijkstra;

2.poj1125 Stockbroker Grapevine(基本)

这个是简单Floyd,需要求出的是每对顶点之间的最短路径;

然后找到那个所需时间最小的那个人中的所需时间;

3.poj 1502 MPI Maelstrom(基本)

这题是邻接矩阵的Dijkstra就可以解决的;

直接水之;

4.poj 1511 Invitation Cards(中等)

这个时间上有点卡了。Dijkstra,bellman可能会TLE;用SPFA+邻接表可以过的;

有个地方注意一下就好了,每个志愿者回来的时候的最短路径;将原图的每条边反向一下,对端点1再来

SPFA就可以来;

正向图的结果+逆向图的结果就是所求;

5.poj 1724 ROADS(中等偏上)

题意是在一定的coins的限制下的最短路径;可以用Dijkstra的变形;

用邻接边来存储边;

 松弛过程中用优先队列(边的长度短的优先)来存储边,将符合条件(coins限制)的边都加入优先队列;

直到找到延伸到最后一个顶点即可终止循环; 因为最先到达的一定是最短路径,在coins的限制条件下;

6.poj1797 Heavy Transportation(中等)

从端点1到端点n的能够通过的最大载重;

可以用Dijkstra变形一下,在松弛时要改变一下松弛的条件;

另外results数组中存储的不是每个点到1的最短距离,而是能够通过的最大载重;

这题的输出让我灰常无语,以后输出要看清啦。。

7.poj 1860 currency exchange(基本)

这个是bellman_ford的经典应用;一个套汇问题,就是通过一系列的货币交换能够到达价值增加的目的;

就是类似判断有没有负权回路;

类似与poj2240,poj3259;

8.poj2240 Arbitrage(基本)

这个是poj1860的简化版本;就不多说了。。

直接bellman水之;

9.poj 2253 Frogger(中等)

和poj1797类似,所求的正好相反,也是Dijkstra的变形经典应用;

改变一下松弛时的条件;

10.poj 2387 Till the Cows come home(基本)

 注意其中可能有重边;然后就是赤裸的Dijkstra;

11.poj 2502 Subway(基本)

可以用Floyd来搞定,关键是哪个边的存储,存储后就是灰常简单的Floyd了;

12.poj 3013 Big Christmas Tree(中等)

这个要有个重要的转化;首先price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).

这句指出每条边的代价为该边所有子孙节点权值之和乘以该边的权值。

换个角度就是每个节点的代价为该节点到根节点的所有边的权值乘以该节点的权值。

其实就是求从端点1到每个点的最短路径*改点的权值,,然后之和;

貌似,数据有点大,用SPFA吧。。

13.poj 3037 Skiing(中等)

这个题有点意思;刚开始想用bfs;

后来发现对于每个点从该点出发的速度是恒定的,例如从a->b->c;则c出发的速度就是V*2^(A-B)*2^(B-C)=V*2^(A-C);

所以直接求最短路径就可以了,边也知道了。用spfa。。

14.poj 3159 Candies(中等)

我靠,这个题时间卡的好紧啊!我的spfa是1400ms,时限是1500ms,汗一下;

题意有点难理解,想明白了,其实就是求一个从1->n的最短路径;

15.poj 3259 Wormholes(简单)

这个题和poj1860,poj3259基本一样;

求负权回路是否存在;用bellman直接水之;

16.poj 3268 Silver Cow Party(基本)

Dijkstra可以直接过的。。只不过求的有变化;

17.poj 3377Ferry Lanes(中等)

这题可以用最短路做的;但是我看和导论那个流水线那个dp例子灰常像;

于是就dp过了,其中有个地方需要注意,dp的话,就是可以需要检查两端的情况;

有兴趣的可以两种都试试;

18.poj 3615 Cow Hurdles(中等)

Floyd求出每个端点之间的路径中最大高度是最小的那个最大高度;

要改变一下松弛的条件; 

19.poj 3660 Cow Contest(中等)

这个题有点topsort的意思,其实可以用Floyd来做,而且用的很巧妙;

邻接矩阵中用0,1,2来分别存储关系不能确定,在之前,在之后;

然后判断每个点哪行,如果除了对角线处,没有0出现的话,那么它的位置就可以确定了。。
上一篇:迪杰斯特拉(Dijkstra)算法


下一篇:最短路学习笔记