最短路模板 - Floyd / Dijkstra
Floyd算法:
写得很好的博客:最短路径问题---Floyd算法详解
算法的特点:
弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或无向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包。
算法的思路:
通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入两个矩阵,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。矩阵P中的元素b[i][j],表示顶点i到顶点j经过了b[i][j]记录的值所表示的顶点。
假设图G中顶点个数为N,则需要对矩阵D和矩阵P进行N次更新。初始时,矩阵D中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞,矩阵P的值为顶点b[i][j]的j的值。 接下来开始,对矩阵D进行N次更新。第1次更新时,如果”a[i][j]的距离” > “a[i][0]+a[0][j]”(a[i][0]+a[0][j]表示”i与j之间经过第1个顶点的距离”),则更新a[i][j]为”a[i][0]+a[0][j]”,更新b[i][j]=b[i][0]。 同理,第k次更新时,如果”a[i][j]的距离” > “a[i][k-1]+a[k-1][j]”,则更新a[i][j]为”a[i][k-1]+a[k-1][j]”,b[i][j]=b[i][k-1]。更新N次之后,操作完成!
代码很短耶 一会都可以背下来了。时间复杂度为O(n^3)
1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 using namespace std;
5 const int INF = 0x3f3f3f;
6
7 int ma[105][105], n, m;
8 void floyd()
9 {
10 for(int k = 1; k <= n; k++)
11 for(int i = 1; i <= n; i++)
12 for(int j = 1; j <= n; j++)
13 ma[i][j] = min(ma[i][j],ma[i][k]+ma[k][j]);
14 }
15 int main()
16 {
17 while(cin >> n >> m && n && m){
18 memset(ma,INF,sizeof(ma));
19 for(int a,b,c,i = 0; i < m; i++){
20 cin >> a >> b >> c;
21 ma[a][b] = ma[b][a] = min(ma[a][b],c);
22 }
23 floyd();
24 cout << ma[1][n] << endl;
25 }
26 return 0;
27 }
Dijkstra算法:
写得很好的博客:Dijkstra 最短路算法
Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的
/*可以输入以下数据进行验证第一行两个整数 n m。n 表示顶点个数(顶点编号为 1~n),m 表示边的条数。接下来 m 行表示,每行有 3 个数 x y z。表示顶点 x 到顶点 y 边的权值为 z。 6 9 1 2 1 1 3 12 2 3 9 2 4 3 3 5 5 4 3 4 4 5 13 4 6 15 5 6 4 运行结果是 0 1 8 4 13 17 时间复杂度:O(N^2) */ #include<iostream> #include<algorithm> using namespace std; const int INF = 0x3f3f3f; int main() { int n, m; int e[10][10], dis[10], book[10]; cin >> n >> m; //初始化 for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) if(i == j) e[i][j] = 0; else e[i][j] = INF; //读边 for(int a,b,c,i = 1; i <= m; i++){ cin >> a >> b >> c; e[a][b] = c; } //dis初始化 for(int i = 1; i <= n; i++) dis[i] = e[1][i]; //book初始化 for(int i = 1; i <= n; i++) book[i] = 0; book[1] = 1; //从点1开 //Dijkstra: int minn, u; for(int i = 1; i <= n-1; i++){ //先找离1最近的点: minn = INF; for(int j = 1; j <= n; j++) if(book[j] == 0 && dis[j] < minn){ minn = dis[j]; u = j; } book[u] = 1; for(int v = 1; v <= n; v++) if(e[u][v] < INF){ if(dis[v] > dis[u]+e[u][v]) dis[v] = dis[u]+e[u][v]; } } //输出点1到每条边的距离: for(int i = 1; i <= n; i++) cout << dis[i] << " "; return 0; }
我jio得 大佬们都已经写得很好啦。还有补充的,以后有了再加。
还有几个其他的最短路算法
未完待续.......