最短路径的三种算法

ps:给17级讲最短路径时候自己写的课件

目录

最短路径... 1

概述: 1

Floyd算法(弗洛伊德算法)复杂度O(n^3) 3

Dijkstra算法(迪杰斯特拉算法)复杂度O(nlog2n) 5

SPFA算法(Shortest Path Fast Algorithm的缩写) 12

附录:... 12

Floyd代码... 12

Dijkstra O(n^2),链式前向星... 13

Dijkstra + priority_queue + 链式前向星... 15

最短路径 概述:

最短路径的三种算法

最短路径的三种算法

假设有一个图,点表示城市,边表示路径长度。

如图,从点(2)到点(4)有若干总走法,比如

最短路径的三种算法

(2)->(3)->(4), 这么走路径长度是4。

最短路径的三种算法

也可以(2)->(3)->(1)->(4) 这样路径长度是15。当图有上万个点的时候就无法用人工直接求任意两点的路径,哪一条是最短的。最短路径就是解决这类问题。

例题:?pid=1499

Floyd算法(弗洛伊德算法)复杂度O(n^3)

const int inf = 0x3f3f3f3f;

由于某些情况下避免正无穷加正无穷加成负无穷,所以正无穷有时不用0x7FFFFFFF, 用0x3f3f3f3f,或者1<<29, 1e9.

这个算法只能用邻接矩阵存图, 我们先初始化一下矩阵

void init() {   ///初始化矩阵

for(int i = 1; i <= n; i ++ ) {

for(int j = 1; j <= n; j ++ ) {

if(i == j) {

mp[i][j] = 0; ///自己到自己的距离0

} else {

mp[i][j] = inf;///否则都是inf

}

}

}

}

 

然后读入一条u->v权值为w的边。对于矩阵mp[u][v]记录的是u->v的边的长度。对于无向图,mp[u][v]和mp[v][u]是相等的。而因为我们求的是最短路, u->v的路有多条我们只要存最短的。

scanf("%d %d %d", &u, &v, &w);

mp[u][v] = mp[v][u] = min(mp[u][v], w);

 

存好矩阵后我们跑floyd算法,核心代码就这几行

for(int k = 0; k < n; k ++ ) {

for(int i = 0; i < n; i ++ ) {

for(int j = 0; j < n; j ++ ) {

mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);

}

}

}

 

然后矩阵mp[s][t]的值就是s->t的最短路径。对于这题来说就是

printf("%d\n", mp[s][t] == inf ? -1 : mp[s][t]);

 

下面我们来解释一下floyd的三层循环。

最短路径的三种算法

我们发现(i)->(j)的最短路径可能是之间i->j,也可能是经过中间点i->k->j。

如果我们用dp[i][j]表示u->v的最短路径。那么

dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

然后看循环。

当k = 0时

枚举I,j.我们尝试让编号0的中点。优化我们的最短距离。

矩阵成为了经过0点优化过的最短距离。

K = 1时,我们又枚举I,j。让矩阵成为经过中间点0,1的最短路矩阵。

以此类推

。。。。

来自知乎的解释

最短路径的三种算法

最短路径的三种算法

优点:好写,核心代码总共就4行。经常扩展出各种图上动态规划

缺点:复杂度高。点的数量1000的图就容易TLE

Dijkstra算法(迪杰斯特拉算法)复杂度O(nlog2n)

最短路径的三种算法

我们先有张图,我们要求1->5的最短路径是什么。

换个问题,我们要求一个dist数组,dist[i]表示起点到i的最短路径。

如果起点是1,初始化dist[1] = 0,其余都是正无穷

最短路径的三种算法

我们的dist[]数组已经完成了dist[1](蓝色),和1相连的有两条边。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggdps.html