1,最短路径的概念:

1,从有向图中某一顶点(起始顶点)到达另一顶点(终止顶点)的路径中,其权值之和最小的路径;

2,问题的提法:

1,给定一个带权有向图 G 与起始顶点 v,求从 v 到 G 中其它顶点的最短路径(每条边上都存在有意义的权值);

2,Dijkstra 算法核心是通过已知最短路径寻找未知最短路径;

3,解决思路:

1,Dijkstra 提出按路径长度的递增次序,逐步产生最短路径;

1,首先求出长度最短的一条最短路径,再参照它求出长度次短的一条最短路径,依次类推,直到从起始顶点 v 到其它各顶点的最短路径全部求出为止;

2,核心是通过递归的方式将从起始顶点到其他各顶点的最短路径全部求出来;

4,准备工作:

1,辅助数组:Array<E> dist;

1,dist[i] 表示当前从起始顶点 v0 到顶点 vi 的路径长度;

2,初始设置:

1,若从起始顶点 v0 到顶点 vi 有边:dist[i] 为该边上的权值;

2,若从起始顶点 v0 到顶点 vi 无边:dist[i] 为无穷大;

5,Dijkstra 算法演示:

1,由非空顶点集和边集这两个图的基本定义可知,集合在图的算法分析中的重要性,而集合在数据结构中常表现为数组;

2,每次关注的是刚刚加入 S 集合的顶点到其他顶点的连接,通过刚刚求得的最短路径值来求出抵达其他顶点的可能的最短路径值,这就是核心;

6,Dijkstra 算法步骤:

7,Dijkstra 算法精髓:

1,S 集合内的顶点是已经找到最短路径的顶点;

2,v0 到 w 的最短路径只能通过 S 集内的顶点;

3,dist[w] 可能改变:

8,如何记录最短路径上的各个顶点?

1,定义辅助数组:

1,Array<int> path;

1,path[i] 表示当前路径上的顶点 i 的前驱顶点;

2,初始化:path = {-1};

3,修改:

9,Dijkstra 算法流程图:

10,Dijkstra 最短路径算法:

    /* 两个顶点之间最短路径,返回的数组表示两个最短路径上面的顶点 */
SharedPointer< Array<int> > dijkstra(int i, int j, const E& LIMIT) // O(n*n)
{
LinkQueue<int> ret; // 保存最短路径上面的顶点 if( ( <= i) && (i < vCount()) && ( <= j) && (j < vCount()) )
{
DynamicArray<E> dist(vCount()); // 用于存储路径值
DynamicArray<int> path(vCount()); // 用于存储当前结点的前驱结点
DynamicArray<bool> mark(vCount()); // 标记顶点是否进入 S 集合 /* 原材料初始化 */
for(int k=; k<vCount(); k++)
{
mark[k] = false; // 顶点都没在 S 集合中
path[k] = -; // 路径没有顶点前驱 dist[k] = isAdjacent(i, k) ? (path[k]=i,getEdge(i, k)) : LIMIT; // 如果初始结点和其他结点有连接,则设置为边上的权值,否则味无穷大;同时也要更新 path 数组,逗号表达式当前顶点 k 的前驱顶点是 i
} mark[i] = true; // 将起始顶点放入 S 集合中 /* 大循环 */
for(int k=; k<vCount(); k++)
{
E m = LIMIT;
int u = -; /* 遍历 dist 数组,从非S集合中找到到S 集合中顶点的最小路径值 */
for(int w=; w<vCount(); w++)
{
if( !mark[w] && (dist[w] < m) ) // 没有被标记的非 S 集中的点找最小值,更新小的值就是找最小路径值
{
m = dist[w]; // 找到了最小路径值
u = w; // 最短路径记录的顶点
}
} /* 判断是否有最小路径被找到,防止只有顶点没有边 */
if( u == - )
{
break; // 只有顶点没有边,找不到两点间最短路径,因为此时 dist 数组都是理论最大值,找不到最小值,直接跳出
} mark[u] = true; // 在非 S 集中找到了顶点 u 对应的路径值是最小值,放入 S 集合 /* 算法核心:通过已知路径,推出 S 集合到非 S 集合顶点最短路径,由新加入的 u 来推动;这里的 w 是非 S 集合中的点,对其遍历;所有顶点都进入 S 集合中的时候,算法结束*/
for(int w=; w<vCount(); w++)
{
/* 以起始顶点 i 到 u 顶点的最短路径为基础,来计算通过已知最短路径所得到的到其它顶点路径是否最小,如果更小,则更新 dist 数组,这里的 w 是最小权值顶点 u 的邻接顶点,只要更小,就要更新 */
if( !mark[w] && isAdjacent(u, w) && (dist[u] + getEdge(u, w) < dist[w]) )
{
dist[w] = dist[u] + getEdge(u, w);
path[w] = u; // 本次前驱顶点都是顶点 u 所代表的顶点
}
}
} LinkStack<int> s; s.push(j); // 终止顶点 j 先放入栈中; /* 将从起始顶点 i 到终值顶点 j 的点先放到栈中去;前驱结点的访问方式、值当做位置;值就是前面的顶点,所以直接把值压入进栈*/
for(int k=path[j]; k!=-; k=path[k])
{
s.push(k);
} /* path 中保存的顶点顺序是逆序的,通过栈中转下,调整过来; */
while( s.size() > )
{
ret.add(s.top()); s.pop();
}
}
else
{
THROW_EXCEPTION(InvalidParameterException, "Index <i, j> is invalid ...");
} /* 最终最短路径经历顶点数至少有 2 个,否则 i 到 j 是不可达的,最多多少顶点是不知道的 */
if( ret.length() < )
{
THROW_EXCEPTION(ArithmeticException, "There is no path from i to j ...");
} return toArray(ret); // 放到数组里面
}

11,Dijkstra 最短路径算法测试代码:

 #include <iostream>
#include "MatrixGraph.h"
#include "ListGraph.h" using namespace std;
using namespace DTLib; template< typename V, typename E >
Graph<V, E>& GraphEasy()
{
   static MatrixGraph<, V, E> g; g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
   g.setEdge(, , ); return g;
} template< typename V, typename E >
Graph<V, E>& GraphComplex()
{
   static ListGraph<V, E> g(); g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
g.setEdge(, , );
   g.setEdge(, , ); return g;
} int main()
{
Graph<int, int>& g = GraphComplex<int, int>();
   SharedPointer< Array<int> > p = g.dijkstra(, , ); for(int i=; i<p->length(); i++)
{
cout << (*p)[i] << " ";
   }    cout << endl; return ;
}

12,小结:

1,Dijkstra 最短路径算法是基于递推的思想完成的;

2,起始顶点到其他各顶点的最短路径通过动态推导得到;

3,未标记顶点的最短路径只能由已标记顶点计算得出;

4,算法的最终结果是起始顶点到其它各顶点的最短路径;

图——图的Dijkstra法最短路径实现的更多相关文章

  1. c/c++ 图的创建及图的相关函数(链表法)

    c/c++ 图的创建及图的相关函数(链表法) 图的概念 图由点和线组成 知道了图中有多少个点,和哪些点之间有线,就可以把一张图描绘出来 点之间的线,分有方向和无方向 创建图 创建图,实际就是创建出节点 ...

  2. Floyd-Warshall求图中任意两点的最短路径

    原创 除了DFS和BFS求图中最短路径的方法,算法Floyd-Warshall也可以求图中任意两点的最短路径. 从图中任取两点A.B,A到B的最短路径无非只有两种情况: 1:A直接到B这条路径即是最短 ...

  3. 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

    题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...

  4. 算法-迪杰斯特拉算法(dijkstra)-最短路径

    迪杰斯特拉算法(dijkstra)-最短路径 简介: 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中 ...

  5. 图——图的Floyd法最短路径实现

    1,Dijkstra 算法一次性求得起始顶点到所有其它顶点的最短路径,如果想要求解任意两个顶点之间的最短路径,可将图中顶点作为起始顶点执行 n 次 Dijkstra 算法就可以了: 2,可能解决方案: ...

  6. 算法-图(1)Dijkstra求最短路径

    数组dist[],是当前求到的顶点v到顶点j的最短路径长度 数组path[]存放求到的最短路径,如path[4]=2,path[2]=3,path[3]=0,则路径{0,3,2,4}就是0到4的最短路 ...

  7. hdu 3499 flight 【分层图】+【Dijkstra】

    <题目链接> 题目大意: 现在给你一些点,这些点之间存在一些有向边,每条边都有对应的边权,有一次机会能够使某条边的边权变为原来的1/2,求从起点到终点的最短距离. 解题分析: 分层图最短路 ...

  8. BZOJ 1579: [Usaco2009 Feb]Revamping Trails 道路升级 分层图最短路 + Dijkstra

    Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i ...

  9. 图——图的Prim法最小生成树实现

    1,运营商的挑战: 1,在下图标出的城市间架设一条通信线路: 2,要求: 1,任意两个城市间都能够通信: 2,将架设成本降至最低: 2,问题抽象: 1,如何在图中选择 n - 1 条边使得 n 个顶点 ...

随机推荐

  1. 【NOIP2016提高A组模拟8.19】(雅礼联考day2)树上路径

    题目 给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E.(k为路径p上的边的权值和). 分析 点分治,设当前为x的,求在以x为根的子树中,经过x的路径(包括起点或 ...

  2. 工作笔记--js-点赞按钮和踩踩按钮互斥??怎么写?

    效果图: html: css: .an{ margin-top:0px; position: relative; .popzframe,.popcframe{ display: none; word- ...

  3. UVa 10603 Fill (BFS && 经典模拟倒水 && 隐式图)

    题意 : 有装满水的6升的杯子.空的3升杯子和1升杯子,3个杯子中都没有刻度.不使用道具情况下,是否可量出4升水呢? 你的任务是解决一般性的问题:设3个杯子的容量分别为a, b, c,最初只有第3个杯 ...

  4. ubuntu下恢复被rm删除的文件

    ubuntu是文件系统,不像windows系统划分盘符(C/D/E/etc...盘).ubuntu对磁盘划分分区,可以使用extundelete恢复ext3/ext4格式的磁盘分区. 其中,ext3/ ...

  5. Navicat使用与python操作数据库

    一.Navicat使用 1.下载地址: <https://pan.baidu.com/s/1bpo5mqj> 2.测试+链接数据库,新建库 3.新建表,新增字段+类型+约束 4.设计表:外 ...

  6. BZOJ 2281 Luogu P2490 [SDOI2011]黑白棋 (博弈论、DP计数)

    怎么SDOI2011和SDOI2019的两道题这么像啊..(虽然并不完全一样) 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?i ...

  7. oracle SQL查询number字段精度丢失之解决方法

    解决办法: -- 3.3:表示原始数据 --fm9999999990.0000:表示保留到小数点后4位,若不存在则用0补位. ),'fm9999999990.0000') as demo from d ...

  8. Java数据结构之排序---插入排序

    插入排序的基本介绍: 插入排序是对想要排序的序列以插入的方式寻找该元素的适当的位置,从而达到排序的目的. 插入排序的基本思想: 把n个待排序的元素看成一个有序表和一个无序表,开始时,有序表只有一个元素 ...

  9. wannafly 练习赛11 F 求子树(树上莫队+换根)

    链接:https://www.nowcoder.com/acm/contest/59/F 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64b ...

  10. 看看 Delphi XE2 为 VCL 提供的 14 种样式

    看看 Delphi XE2 为 VCL 提供的 14 种样式 其实只提供了 13 个 vsf 样式文件, 还有默认的 Windows 样式, 共 14 种. 在空白窗体上添加 ListBox1 等控件 ...