最短路算法(floyed+Dijkstra+bellman-ford+SPFA)

最短路算法简单模板

一.floyed算法

首先对于floyed算法来说就是最短路径的动态规划解法,时间复杂度为O(n^3) 适用于图中所有点与点之间的最短路径的算法,一般适用于点n较小的情况。

Floyed算法有三层循环,循环的层次先后顺序也是比较重要的,分别为k ,i,j;因为dis[k][i][j]代表的是i节点到j节点的最短路如果中间经过节点k的话dis[k][i][j] =dis[k-1][i][k]+dis[k-1][k][j];否则dis[k][i][j] = dis[k-1][i][j];所以说我们要求第k个节点的话就必须先把所有的k-1求出来。而此处的三维dis数组正如背包问题一样优化为二维数组。

对于任意两个节点i,j来说;要想从节点i到达节点j的话有两种情况:

  1. 由i直接到达j
  2. 由i经过若干个k节点到达j

所以dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);

HDU 2544 最短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int INF = 0x3f3f3f;
 6 int n, m, mp[110][110];
 7 void floyed()
 8 {
 9     for (int k = 1; k <= n; k++)
10         for (int i = 1; i <= n; i++)
11             for (int j = 1; j <= n; j++)
12                 mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
13 }
14 int main()
15 {
16     ios::sync_with_stdio(false);
17     while ((cin >> n >> m)&&n&&m) {
18         memset(mp, INF, sizeof(mp));
19         for (int a, b, c, i = 0; i < m; i++) {
20             cin >> a >> b >> c;
21             mp[a][b] = mp[b][a] =  min(mp[a][b], c);
22         }
23         floyed();
24         cout << mp[1][n] << endl;
25     }
26     return 0;
27 }

二.Dijkstra算法

关于Dijkstra算法(贪心)的推断过程我就不详细的讲啦,我会的别人都已经讲完了而且还比我详细,在这里向大家推荐一篇写的不错的博客!https://www.cnblogs.com/nigang/p/3658990.html

这位博主讲的还是很详细的,图解也很清晰明了

下面我还是通过一个例题来讲解代码吧!(同floyed例题)

邻接表的Dijkstra:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int INF = 0x3f3f3f;
 6 int n, m, mp[110][110];
 7 int dis[110], vis[110];
 8 void Dijkstra()
 9 {
10     for (int i = 1; i <= n; i++) {
11         vis[i] = 0; dis[i] = mp[1][i];
12     }
13     for (int i = 1; i <= n; i++) {
14         int cnt = INF, k;
15         for (int j = 1; j <= n; j++) {
16             if (!vis[j] && dis[j] < cnt) {
17                 cnt = dis[j];
18                 k = j;
19             }
20         }
21         vis[k] = 1;
22         for (int j = 1; j <= n; j++) {
23             if (!vis[j] && dis[j] > dis[k] + mp[k][j])
24                 dis[j] = dis[k] + mp[k][j];
25         }
26     }
27 }
28 int main()
29 {
30     ios::sync_with_stdio(false);
31     while ((cin >> n >> m)&&n&&m) {
32         memset(mp, INF, sizeof(mp));
33         for (int a, b, c, i = 0; i < m; i++) {
34             cin >> a >> b >> c;
35             mp[a][b] = mp[b][a] =  min(mp[a][b], c);
36         }
37         Dijkstra();
38         cout << dis[n] << endl;
39     }
40     return 0;
41 }

堆优化后的Dijkstra

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<bitset>
 5 #include<vector>
 6 #include<queue>
 7
 8 using namespace std;
 9 const int INF = 1 << 30;
10 const int maxn = 110;
11 struct node{
12     int to, cost;
13     node() {}
14     node(int a, int b) :to(a), cost(b) {}
15     bool operator<(const node&a)const {
16         if (cost == a.cost)return to < a.to;
17         return cost > a.cost;
18     }
19 };
20 vector<node>e[maxn];
21 int n, m, dis[maxn];
22 void Dijkstra(int s)
23 {
24     for (int i = 1; i <= n; i++)dis[i] = INF;
25     dis[s] = 0;
26     priority_queue<node>Q;
27     Q.push(node(s, dis[s]));
28     while (!Q.empty()) {
29         node t = Q.top(); Q.pop();
30         for (int i = 0; i < e[t.to].size(); i++) {
31             int tmp = e[t.to][i].to;
32             if (dis[tmp] > t.cost + e[t.to][i].cost) {
33                 dis[tmp] = t.cost + e[t.to][i].cost;
34                 Q.push(node(tmp, dis[tmp]));
35             }
36         }
37     }
38 }
39 int main()
40 {
41     ios::sync_with_stdio(false);
42     while ((cin >> n >> m)&&(n&&m)) {
43         for (int i = 1; i <= n; i++)e[i].clear();
44         for (int a, b, c, i = 0; i < m; i++) {
45             cin >> a >> b >> c;
46             e[a].push_back(node(b, c));
47             e[b].push_back(node(a, c));
48         }
49         Dijkstra(1);
50         cout << dis[n] << endl;
51     }
52     return 0;
53 }

三.bellman-ford算法

当路径当中出现负权值边的时候Dijkstra算法将不再适用,因为dijkstra由于是贪心的,每次都找一个距源点最近的点,然后将该距离定为这个点到源点的最短路径,但如果存在负权边,那就有可能先通过并不是距源点最近的一个次优点,而是这一个负权值边,所求出的结果可能就不是最短距离了。

算法讲解https://blog.csdn.net/niushuai666/article/details/6791765

模板:无向图。有向图的话边只需要加一次即可

 1 #include<iostream>
 2 #include<algorithm>
 3
 4 using namespace std;
 5 const int INF = 1 << 28;
 6 const int maxn = 10005;
 7 struct node {
 8     int from, to, cost;
 9     node() {}
10     node(int a, int b, int c) :from(a), to(b), cost(c) {}
11 }e[maxn<<1];
12 int n, m, dis[110];
13 bool bellman_ford()
14 {
15     for (int i = 2; i <= n; i++)dis[i] = INF;
16     dis[1] = 0;
17     for (int i = 1; i < n; i++) {
18         int flag = 0;
19         for (int j = 1; j <= 2 * m; j++) {
20             if (dis[e[j].to] > dis[e[j].from] + e[j].cost) {
21                 dis[e[j].to] = dis[e[j].from] + e[j].cost;
22                 flag = 1;
23             }
24         }
25         if (!flag)return true;
26     }
27     for (int j = 1; j <= m; j++)
28         if (dis[e[j].to] > dis[e[j].from] + e[j].cost)
29             return false;
30     return true;
31 }
32 int main()
33 {
34     ios::sync_with_stdio(false);
35     while ((cin >> n >> m)&&n&&m) {
36         for (int a, b, c, i = 1; i <= m; i++) {
37             cin >> a >> b >> c;
38             e[i] = node(a, b, c);
39             e[i + m] = node(b, a, c);
40         }
41         bellman_ford();
42         cout << dis[n] << endl;
43     }
44     return 0;
45 }

四. SPFA 算法<--bellman-ford算法的优化

一篇清晰的算法过程的讲解!https://www.cnblogs.com/bofengyu/p/5004398.html

代码模板如下

例题:POJ 2387

http://poj.org/problem?id=2387

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #include<queue>
 6
 7 using namespace std;
 8 const int maxn = 2010;
 9 const int INF = 0x3f3f3f3f3f;
10 int n, m;
11 struct node{
12     int to, cost;
13     node() {}
14     node(int a, int b) :to(a), cost(b) {}
15 };
16 vector<node> e[maxn];
17 int vis[maxn], f[maxn], dis[maxn];
18 void SPFA(int s)
19 {
20     for (int i = 0; i < maxn; i++) {
21         vis[i] = 0; f[i] = 0;
22         dis[i] = INF;
23     }
24     dis[s] = 0;
25     vis[s] = 1; f[s]++;
26     queue<int>Q;
27     Q.push(s);
28     while (!Q.empty()) {
29         int t = Q.front(); Q.pop();
30         vis[t] = 0;
31         for (int i = 0; i < e[t].size(); i++) {
32             int tmp = e[t][i].to;
33             if (dis[tmp] > dis[t] + e[t][i].cost) {
34                 dis[tmp] = dis[t] + e[t][i].cost;
35                 if (!vis[tmp]) {
36                     vis[tmp] = 1;
37                     Q.push(tmp);
38                     if (++f[tmp] > n)return;
39                 }
40             }
41         }
42     }
43     return;
44 }
45 int main()
46 {
47     ios::sync_with_stdio(false);
48     while (cin >> m >> n) {
49         for (int a, b, c, i = 1; i <= m; i++) {
50             cin >> a >> b >> c;
51             e[a].push_back(node(b, c));
52             e[b].push_back(node(a, c));
53         }
54         SPFA(1);
55         cout << dis[n] << endl;
56     }
57     return 0;
58 }

原文地址:https://www.cnblogs.com/wangrunhu/p/9507865.html

时间: 2024-10-05 04:28:03

最短路算法(floyed+Dijkstra+bellman-ford+SPFA)的相关文章

[算法第一轮复习] 最短路算法之dijkstra

1.算法描述 dijkstra,一种求单源正权图上的最短路的算法 主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止 Dijkstra算法思想为:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中.在加入的过程中,总保持从源

POJ 3013 Big Christmas Tree【最短路变形,DIjkstra堆优化+spfa算法】

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23064   Accepted: 4987 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

POJ 1860 Currency Exchange (Bellman ford)

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22405   Accepted: 8095 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

Book 最短路算法

用HDU2544整理一下最近学的最短路算法 1.Dijkstra算法 原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离 初始时,集合里面只有源点,当每个点u进入集合S时,用d[u]+w[u][v]更新距离 再重复这个步骤,选取S外所有点中d[]最小的进入集合 直到所有的点都进入S集合 局限性:图的边权必须为正 复杂度:O(V*V),堆优化((E+V)logV) (1)用邻接矩阵实现 1 #include<iostream> 2 #include<cstdio>

[ACM] 最短路算法整理(bellman_ford , SPFA , floyed , dijkstra 思想,步骤及模板)

以杭电2544题目为例 最短路 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路.N=M=0

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并

(最短路径算法整理)dijkstra、floyd、bellman-ford、spfa算法模板的整理与介绍

这一篇博客以一些OJ上的题目为载体.整理一下最短路径算法.会陆续的更新... 一.多源最短路算法--floyd算法 floyd算法主要用于求随意两点间的最短路径.也成最短最短路径问题. 核心代码: /** *floyd算法 */ void floyd() { int i, j, k; for (k = 1; k <= n; ++k) {//遍历全部的中间点 for (i = 1; i <= n; ++i) {//遍历全部的起点 for (j = 1; j <= n; ++j) {//遍历

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运