有权图的单源最短路亦被称为Dijkstra算法(单源最短路径),首先要声明这个算法无法解决含有负值圈的图

显然最优解释围绕着红色的圈不停的兜圈,所以基本上所有的算法都挂掉了

排除掉这种情况之后

Dijkstra算法步骤如下:

G={V,E}
1. 初始时令 S={V0},T=V-S={其余顶点},T中顶点对应的距离值
        若存在<V0,Vi>,d(V0,Vi)为<V0,Vi>弧上的权值
        若不存在<V0,Vi>,d(V0,Vi)为∞
2. 从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中(每次从未被收录的顶点中选一个dist最小的收录 (贪心))
3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值

重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止

可以得到证明的是:

若路径是按照递增(非递减)的顺序生成的,则

真正的最短路必须只经过S中的顶点

如果收录v使得s到w的路径变短,则s到w的路径一定经过v,并且v到w有一条边

增加一个v进入S,可能影响另一个w的dist值,w只可能是v一圈的点

下面我们对于下面的有权图举个例子

邻接矩阵的Dijkstra算法实现

下面是伪代码描述以及矩阵的初始化

其函数的C语言描述如下

/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。  */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下:         */
bool IsEdge(MGraph Graph, Vertex V, Vertex W)
{return Graph->G[V][W] <INFINITY ? true : false;
}/*邻接矩阵储存——有权图的单源最短路算法*/
Vertex FindMinDist(MGraph Graph) {/*返回未被收录顶点中的最小dist者*/Vertex MinV, V;int MinDist = INFINITY;for (V = 0; V < Graph->Nv; V++) {if (Visited[V] == false && dist[V] < MinDist) {/*若V未被收录,且dist[V]更小*/MinDist = dist[V];/*更新最小距离*/MinV = V;/*更新最小顶点*/}}if (MinDist < INFINITY)/*若找到最小dist*/return MinV;/*返回对应的顶点下标*/else return ERROR;/*若这样的顶点不存在,返回错误标记*/
}/* dist[]和path[]为全局变量,已经初始化为-1 */
bool Dijkstra(MGraph Graph, Vertex S)
{   /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */Vertex V, W;/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/for (V = 0; V < Graph->Nv; V++) {dist[V] = Graph->G[S][V];if (dist[V] < INFINITY)path[V] = S;elsepath[V] = -1;Visited[V] = false;}/*先将起点收入集合*/dist[S] = 0;Visited[S] = true;while (1){/*找到未被收入顶点中dist最小者*/V = FindMinDist(Graph);if (V == ERROR)/*若这样的V不存在*/break;//算法结束Visited[V] = true;//收录Vfor (W = 0; W < Graph->Nv; W++)//对图中每个顶点Wif (Visited[W] == false && Graph->G[V][W] < INFINITY) {//若W未被收录并且是V的临近点if (Graph->G[V][W] < 0)//若有负边return false;//不能正确解决,返回错误标记if (dist[V] + Graph->G[V][W] < dist[W])//若收录V使得dist[W]变小{dist[W] = dist[V] + Graph->G[V][W];//更新dist[W]path[W] = V;//更新S到W的路径}}}/*while结束*/return true;/*算法执行完毕,返回正确标记*/
}

执行结果嘿嘿,当然没毛病咯


和我们通过肉眼看的结果一样一样的

附上完整代码

#include <stdio.h>
#include <stdlib.h>        #define ERROR 0
#define INFINITY 65535        /* ∞设为双字节无符号整数的最大值65535*/
#define MaxVertexNum 100    /* 最大顶点数设为100 */
typedef int Vertex;         /* 用顶点下标表示顶点,为整型 */
typedef int WeightType;        /* 边的权值设为整型 */
typedef char DataType;        /* 顶点存储的数据类型设为字符型 */int Visited[MaxVertexNum];
int dist[MaxVertexNum];
int path[MaxVertexNum];/* 边的定义 */
typedef struct ENode *PtrToENode;
struct ENode {Vertex V1, V2;      /* 有向边<V1, V2> */WeightType Weight;  /* 权重 */
};
typedef PtrToENode Edge;/* 图结点的定义 */
typedef struct GNode *PtrToGNode;
struct GNode {int Nv;  /* 顶点数 */int Ne;  /* 边数   */WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */
};
typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */MGraph CreateGraph(int VertexNum)
{ /* 初始化一个有VertexNum个顶点但没有边的图 */Vertex V, W;MGraph Graph;Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */Graph->Nv = VertexNum;Graph->Ne = 0;/* 初始化邻接矩阵 *//* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */for (V = 0; V<Graph->Nv; V++)for (W = 0; W<Graph->Nv; W++)Graph->G[V][W] = INFINITY;return Graph;
}void InsertEdge(MGraph Graph, Edge E)
{/* 插入边 <V1, V2> */Graph->G[E->V1][E->V2] = E->Weight;/* 若是无向图,还要插入边<V2, V1> *///Graph->G[E->V2][E->V1] = 1;
}/* IsEdge(Graph, V, W)检查<V, W>是否图Graph中的一条边,即W是否V的邻接点。  */
/* 此函数根据图的不同类型要做不同的实现,关键取决于对不存在的边的表示方法。*/
/* 例如对有权图, 如果不存在的边被初始化为INFINITY, 则函数实现如下:         */
bool IsEdge(MGraph Graph, Vertex V, Vertex W)
{return Graph->G[V][W] <INFINITY ? true : false;
}/*邻接矩阵储存——有权图的单源最短路算法*/
Vertex FindMinDist(MGraph Graph) {/*返回未被收录顶点中的最小dist者*/Vertex MinV, V;int MinDist = INFINITY;for (V = 0; V < Graph->Nv; V++) {if (Visited[V] == false && dist[V] < MinDist) {/*若V未被收录,且dist[V]更小*/MinDist = dist[V];/*更新最小距离*/MinV = V;/*更新最小顶点*/}}if (MinDist < INFINITY)/*若找到最小dist*/return MinV;/*返回对应的顶点下标*/else return ERROR;/*若这样的顶点不存在,返回错误标记*/
}/* dist[]和path[]为全局变量,已经初始化为-1 */
bool Dijkstra(MGraph Graph, Vertex S)
{   /* 以S为出发点对邻接矩阵存储的图Graph进行BFS搜索 */Vertex V, W;/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/for (V = 0; V < Graph->Nv; V++) {dist[V] = Graph->G[S][V];if (dist[V] < INFINITY)path[V] = S;elsepath[V] = -1;Visited[V] = false;}/*先将起点收入集合*/dist[S] = 0;Visited[S] = true;while (1){/*找到未被收入顶点中dist最小者*/V = FindMinDist(Graph);if (V == ERROR)/*若这样的V不存在*/break;//算法结束  Visited[V] = true;//收录V  for (W = 0; W < Graph->Nv; W++)//对图中每个顶点W  if (Visited[W] == false && Graph->G[V][W] < INFINITY) {//若W未被收录并且是V的临近点  if (Graph->G[V][W] < 0)//若有负边  return false;//不能正确解决,返回错误标记  if (dist[V] + Graph->G[V][W] < dist[W])//若收录V使得dist[W]变小  {dist[W] = dist[V] + Graph->G[V][W];//更新dist[W]  path[W] = V;//更新S到W的路径  }}}/*while结束*/return true;/*算法执行完毕,返回正确标记*/
}int main() {MGraph Graph = CreateGraph(7);Graph->Ne = 12;Vertex a[12] = { 0,0,1,1,2,2,3,3,3,3,4,6 };Vertex b[12] = { 1,3,3,4,0,5,2,4,5,6,6,5 };WeightType w[12] = { 2,1,3,10,4,5,2,2,8,4,6,1 };/* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */for (int i = 0; i<Graph->Ne; i++) {Edge E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */E->V1 = a[i]; E->V2 = b[i]; E->Weight = w[i];/* 注意:如果权重不是整型,Weight的读入格式要改 */InsertEdge(Graph, E);}for (int i = 0; i < MaxVertexNum; i++) { Visited[i] = false; dist[i] = INFINITY; path[i] = -1; }Dijkstra(Graph, 0);int i = 0;for (int i = 0; i < Graph->Nv; i++) {printf("点%d到点1的最小距离是:%d  上一步结点是:%d\n", i + 1, dist[i], path[i] + 1);}system("pause");
}

有权图的单源最短路算法相关推荐

  1. C++实现单源最短路算法

    1.单源最短路算法 n个处理器,第一个处理器要广播消息到其他所有的处理器,求需要时间最短是多少(从第一个点出发,求到其他点最短路的最大值) 2.思路 这个基本上没啥可说.看代码理解就是. 3.代码实现 ...

  2. 图算法:2、计算带有负权值的单源最短路径:Bellman-Ford算法

    原文地址:http://www.wutianqi.com/?p=1912 相关文章: 1.Dijkstra算法: http://www.wutianqi.com/?p=1890 2.Floyd算法: ...

  3. 蓝桥杯最短路(java过)spfa单源最短路算法

    spfa 百度百科上spfa的思路为:动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最 ...

  4. Dijkstra(单源最短路算法)

    typedef struct gra{  //顶点 int val; int weight; }graph; graph g[1005][1005],dist[1005]; //图  和  最短路径 ...

  5. 【数据结构笔记24】单源最短路(迪克斯拉Dijkstra算法),多源最短路(弗洛伊德Floyd算法)

    本次笔记内容: 7.1.1 概述 7.1.2 无权图的单源最短路 7.1.3 有权图的单源最短路 7.1.3-s 有权图的单源最短路示例 7.1.4 多源最短路算法 文章目录 最短路径问题 最短路径问 ...

  6. 邻接矩阵和邻接表_[力扣743] 带权邻接表的单源最短路

    题目链接 743. 网络延迟时间 题目描述 有 N 个网络节点,标记为 1 到 N. 给定一个列表 times,表示信号经过有向边的传递时间. times[i] = (u, v, w),其中 u 是源 ...

  7. dijkstra邻接表_[力扣743] 带权邻接表的单源最短路

    题目链接 743. 网络延迟时间 题目描述 有 N 个网络节点,标记为 1 到 N. 给定一个列表 times,表示信号经过有向边的传递时间. times[i] = (u, v, w),其中 u 是源 ...

  8. 算法提高课-图论-单源最短路的建图方式-AcWing 920. 最优乘车:bfs求最短路、建图

    题目分析 来源:acwing 分析: 本题难在抽象建图上,这里采用的建图方式是:同一条公交线路上,前面的站点都可以连一条有向边到其后面的站点,且边权都为1. 由于边权都是1,可以用bfs来求最短路. ...

  9. acwing单源最短路的建图模式总结

    .根据边权的范围以及问题求解的需要,最短路问题可以分为以下 4 种情形,分别用不同的算法求解. • 单源最短路径(固定一个顶点为原点,求源点到其他每个顶点 的最短路径) • 1. 边权非负:Dijks ...

  10. CSP认证201609-4 交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想

    题目分析 来源:acwing 分析: 这题是最短路树.保持原图中所有点到根结点的最短距离不变,然后在原图中选择一些边,使所有点连通的最短路是多长. 最短路径树,是一种使用最短路径算法生成的数据结构树. ...

最新文章

  1. 院长来信 | 英特尔宋继强:疫情之下对科技创新的再思考,科学为源,技术为器...
  2. linux下c md5函数
  3. Setting up Pytorch with Python 3 on Ubuntu(Source code compilation)
  4. Winform中怎样在工具类中对窗体中多个控件进行操作(赋值)
  5. CSS3菜单栏透明兼容问题
  6. javascript dom追加内容的例子
  7. postgresql对于HashJoin算法的Data skew优化与MCV处理
  8. 取消选中目标CALL
  9. 【Virtual DOM】虚拟 DOM 和 Snabbdom 库
  10. 2018 最强“弱密码”排行榜新鲜出炉,123456 再登首
  11. java成绩管理系统代码_[转载]我写的Java学生成绩管理系统源代码
  12. 85条高级AutoCAD工程师绘图技巧(1)
  13. 解析PayPal支付接口的PHP开发方式
  14. aho-corasick php,Aho-Corasick自动机浅析
  15. mysql本机地址_mysql连接时用的IP地址是不是电脑本机上的IP地址呢!
  16. 照片上传分辨率低怎么改?图片分辨率dpi怎么调?
  17. Unsupported major.minor version 52.0 解决方案
  18. 合同法律风险管理 合同签字主体
  19. 网络精英赛模拟练习(4)
  20. Elasticsearch 断路器报错了,怎么办?

热门文章

  1. 【自定义WPS插件xlam】
  2. NPDP,优秀产品经理必备证书
  3. 深入解析CAS算法原理
  4. python手工打码_python云打码
  5. Vue模板语法——插值
  6. 高级PPT动画制作示例
  7. 阿里巴巴规范之POJO类中布尔类型的变量都不要加is前缀详解
  8. Mac大小写切换,中英文切换
  9. 如何解决录音嗡嗡嗡?VoiceMeeter加OBS免费且强大的录音录像解决方案
  10. java如何调用百度地图拾取坐标系统