Dijkstra算法

一.最短路径的最优子结构性质

该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。

假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而 P(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径P'(k,s),那么 P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。则与P(i,j)是从i到j的最短路径相矛盾。因此该性质得证。

二.Dijkstra算法

由上述性质可知,如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点。那么(Vi...Vk)也必定是从i到k的最短 路径。为了求出最短路径,Dijkstra就提出了以最短路径长度递增,逐次生成最短路径的算法。譬如对于源顶点V0,首先选择其直接相邻的顶点中长度最 短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+matrix[i][j]}。根 据这种思路,

假设存在G=<V,E>,源顶点为V0,U={V0},dist[i]记录V0到i的最短距离,path[i]记录从V0到i路径上的i前面的一个顶点。

1.从V-U中选择使dist[i]值最小的顶点i,将i加入到U中;

2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})

3.知道U=V,停止。

三.算法实例

先给出一个无向图

用Dijkstra算法找出以A为起点的单源最短路径步骤如下

代码:

#include <iostream>
#include <cstring>
using namespace std; #define DEBUG 0
#define INF 0x7fffffff
#define MAX 20 int N, V;
int graph[MAX][MAX];
int dist[MAX];
int prev[MAX];
bool visited[MAX]; void PrintPath()
{
for( int i = ; i <= V; i++ )
{
cout << "1 --> " << i << " : " << dist[i] << endl;
} for( int i = ; i <= V; i++ ) //计算从1到每个顶点的距离
{
int path[MAX] = {};
int step = ;
int cur = i;
do
{
path[step++] = cur;
cur = prev[cur];
}
while( cur != - ); //前一个点为-1,则结束 for( int j = step - ; j >= ; j-- )
{
cout << path[j] << " ";
}
cout << endl;
}
} int GetMinDist()
{
int index, min = INF;
for( int i = ; i <= V; i++ )
{
if( !visited[i] && min > dist[i] )
{
min = dist[i];
index = i;
}
}
return index;
} void Dijkstra( int v )
{
for( int i = ; i <= V; i++ )
{
if( graph[v][i] == INF )
{
dist[i] = INF;
prev[i] = -;
}
else
{
dist[i] = graph[v][i];
prev[i] = v;
}
visited[i] = false;
} dist[v] = ;
visited[v] = true; for( int i = ; i < V; i++ ) //迭代V-1次,不用计算源点了,还剩下V-1个需要计算的顶点
{
int u = GetMinDist(); visited[u] = true; for( int j = ; j <= V; j++ ) //更新dist数组
{
if( visited[j] == false && graph[u][j] != INF && dist[u] != INF && dist[j] > dist[u] + graph[u][j] )
{
dist[j] = dist[u] + graph[u][j];
prev[j] = u;
}
}
}
} void InitData()
{
memset( visited, false, sizeof( visited ) ); //初始化visited for( int i = ; i <= V; i++ )
{
for( int j = ; j <= V; j++ )
{
graph[i][j] = INF;
}
dist[i] = INF;
}
} int main()
{
int a, b, value;
while( cin >> V, V ) // 输入顶点数
{
cin >> N; //输入边数
InitData();
for( int i = ; i <= N; i++ )
{
cin >> a >> b >> value;
graph[a][b] = graph[b][a] = value;
} Dijkstra( );
PrintPath();
}
}

输入文件:

/*

6 10
1 2 4
1 3 8
2 3 3
2 4 4
2 5 6
3 4 2
3 5 2
4 5 4
4 6 9
5 6 4 result :
1 --> 1 : 0
1 --> 2 : 4
1 --> 3 : 7
1 --> 4 : 8
1 --> 5 : 9
1 --> 6 : 13
1
1 2
1 2 3
1 2 4
1 2 3 5
1 2 3 5 6 */

Floyd算法

1.算法思想原理:

Floyd算法是一个经典的动态规划算法。从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,则设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。

2.算法描述:

a.从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。   

b.对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短。如果是更新它。

3.Floyd算法过程矩阵的计算----十字交叉法

方法:两条线,从左上角开始计算一直到右下角 如下所示

给出矩阵,其中矩阵A是邻接矩阵,而矩阵Path记录u,v两点之间最短路径所必须经过的点

相应计算方法如下:

最后A3即为所求结果.

算法实现:

#include <iostream>

using namespace std;

#define INF 65536
#define MAX 20 int graph[MAX][MAX];
int KeyPoint[MAX][MAX];
int V, E; void PrintPath()
{
cout << graph[][V] << endl; int path[MAX];
int step = ;
int cur = V; while(cur != ) {
path[step++] = cur;
cur = KeyPoint[][cur];
} path[step++] = ; //保存起点 for (int j = step - ; j >= ; j--)
{
cout << path[j] << " ";
}
cout << endl;
} void Floyd()
{
graph[][] = ; for(int k = ; k <= V; k++) //对于每一个节点k,检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立
for(int i = ; i <= V; i++)
for(int j = ; j <= V; j++)
if(graph[i][j] > graph[i][k] + graph[k][j])
{
graph[i][j] = graph[i][k] + graph[k][j];
KeyPoint[i][j] = k;
}
PrintPath();
} void InitData()
{
for(int i = ; i <= V; i++)
{
for(int j = ; j <= V; j++)
{
graph[i][j] = INF;
KeyPoint[i][j] = ;
}
}
} int main()
{
int a, b, length;
while(cin >> V, V) //输入顶点数
{
InitData(); cin >> E; //输入边数
for(int i = ; i <= E; i++)
{
cin >> a >> b >> length;
graph[a][b] = graph[b][a] = length;
} Floyd();
}
}

测试用例

/*

6 10
1 2 4
1 3 8
2 3 3
2 4 4
2 5 6
3 4 2
3 5 2
4 5 4
4 6 9
5 6 4 result:
13
1 2 3 5 6 */

Algorithm --> Dijkstra和Floyd最短路径算法的更多相关文章

  1. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

  2. Floyd最短路径算法

    看完这篇文章写的小程序,Floyd最短路径算法,求从一个点到另一个点的最短距离,中间可以经过其他任意个点.三个for循环,从i到j依次经过k的最短距离,最外层for循环是经过点K,内部两个循环是从i( ...

  3. Dijkstra单源点最短路径算法

    学习参考: Dijkstra算法(单源最短路径) 最短路径—Dijkstra算法和Floyd算法 使用的图结构: 邻接矩阵: -1 20 -1 25 80-1 -1 40 -1 -1-1 -1 -1 ...

  4. Floyd最短路径算法(来自微信公众号“算法爱好者”改编)

    暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数字表 ...

  5. 【模板 && 拓扑】 Dijkstra 单源最短路径算法

    话不多说上代码 链式前向星233 #include<bits/stdc++.h> using namespace std; ,_max=0x3fffffff; //链式前向星 struct ...

  6. 图之单源Dijkstra算法、带负权值最短路径算法

    1.图类基本组成 存储在邻接表中的基本项 /** * Represents an edge in the graph * */ class Edge implements Comparable< ...

  7. 一篇文章讲透Dijkstra最短路径算法

    Dijkstra是典型最短路径算法,计算一个起始节点到路径中其他所有节点的最短路径的算法和思想.在一些专业课程中如数据结构,图论,运筹学等都有介绍.其思想是一种基础的求最短路径的算法,通过基础思想的变 ...

  8. Johnson 全源最短路径算法

    解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...

  9. Floyd-Warshall 全源最短路径算法

    Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...

随机推荐

  1. mysql常用基础操作语法(六)--对数据排序和限制结果数量的条件查询【命令行模式】

    1.使用order by对查询的结果进行排序,asc升序,desc降序: 也可以在order by后指定多个字段名和排序方式进行多级排序: 2.使用limit限制查询结果的数量: 上图中的0,代表查询 ...

  2. dedecms 使用自由列表实现首页列表分页

  3. AM335x(TQ335x)学习笔记——触摸屏驱动编写

    前面几篇文章已经通过配置DTS的方式完成了多个驱动的移植,接下来我们解决TQ335x的触摸驱动问题.由于种种原因,TQ335x的触摸屏驱动是以模块方式提供的,且Linux官方内核中也没有带该触摸屏的驱 ...

  4. linux虚拟机中安装mongodb

    今天在linux虚拟机中安装了mongodb数据库,安装过程主要参照了网上的一片文档,大部分地方都没有多大区别,只是在某些细节上有所改变. 我参考的文档是:http://my.oschina.net/ ...

  5. DirectX:函数可以连接任意两个filter

    函数可以连接任意两个filter HRESULT ConnectFilters( IBaseFilter *pSrc, IBaseFilter *pDest ) { IPin *pIn = 0; IP ...

  6. xml的Dom4j解析规则

    一,xml的样本 <?xml version="1.0" encoding="utf-8"?> <contactList> <co ...

  7. Java面试题积累

    持续积累中... 1.Java支持的数据类型有哪些?什么是自动拆装箱? 数据类型分为两大种,基本类型和引用类型. 基本类型有8种:byte short int long char float doub ...

  8. SpringBean基础装配

            首先,让我们先对Bean进行理解:什么是Bean,为什么要有Bean,如何装配Bean:         1,什么是Bean?             Bean你可以看成是一个组件,在 ...

  9. 使用sourceTree向码云提交代码时 push 错误 (或认证失败)解决办法

     如果出现push不进去或者使用命令push认证失败时,很可能是你密码有误或者用户冲突,解决办法如下: 1.进入目录,找到文件后先备份一下 注意:appData可能隐藏了,若是隐藏,先让其显示  2. ...

  10. Codeforces Round #466 (Div. 2)

    所有的题目都可以在CodeForces上查看 中间看起来有很多场比赛我没有写了 其实是因为有题目没改完 因为我不想改,所以就没有写了(大部分题目还是改完了的) 我还是觉得如果是打了的比赛就一场一场写比 ...