单源最短路径:从顶点v可达顶点u表示为v->u,在所有的可达路径中存在一条权值最小的路径,则这条路径叫做v到u的最短路径。那么单源最短路径指的是:求出给定源点s到其他所有顶点的最短路径。 最短路径的性质:对于一给定的带权图G=(V,G),所定义的加权函数为w:E->R。设p=<v1,v2,v3,……,vk>是从v1到vk的最短路径。对于任意i,j,其中1<=i<=j<=k,设pij=<vi,vi+1,……,vj>为p中从顶点vi到顶点vj的子路径。那么,pij是从vi到vj的最短路径。(最短路径的子路径是最短路径) 最短路径中不存在负权回路,因为如果存在负权回路,我们总是可以顺着已经找的“最短”路径,再穿过负权回路而获得一条权值更小的路径。这样无限次的穿过,我们得到这条路径的权值为负无穷。同样,最短路径中也不存在正权回路,对于权值为零的回路可有可无。 路径松弛性质:如果p=<v0,v1,……,vk>是从s=v0到vk的最短路径,而且p的边按照(v0,v1),(v1,v2),……,(vk-1,vk)的顺序进行松弛,那么d[vk]=sp(s,vk)(表示s到vk的最短路径上的权值),这个性质的保持并不受其他松弛操作的影响,即使它们与p的边上的松弛操作混合在一起也是一样的。 下面介绍三种方法求最短路径: (1)Bellman-Ford算法,该算法用来解决一般的单源最短路径问题(边的权值可以为负,但是不存在负权回路)。此方法可以检测是否有存在从源点可达的负权回路。 (2)在有向无环图中,我们可以根据图中顶点的拓扑顺序,在线性时间内计算出单源最短路径路径的值。 (3)Dijkstra算法,运行时间比Bellman-Ford算法时间低,但此算法有一个不足之处是:必须要求边上的权值非负。 在介绍上述三个算法之前,我们先介绍两个基本操作:初始化操作和松弛操作。 初始化操作的伪代码:其中d[v]表示从源点到v的最短路径上权值的上界,p[v]表示最短路径上v的前驱顶点。Initialize-Single-Source(s) for each vertex v∈V[G] do d[v] <- ∞ p[v] <- NIL d[s] <- 0;
松弛操作的伪代码:在松弛一条边(u,v)时,要测试是否可以通过u,对目前为止到v的最短路径进行更新。如果可以更新的话,则更新d[v]和p[v]。一次松弛操作可以减少最短路径估计值d[v],并且更新v的前驱p[v]。Relax(u,v,w) <span style="white-space:pre"> </span>if d[v] > d[u] + w(u,v) then d[v] <- d[u] + w(u,v) p[v] <- u;
方法一:Bellman-Ford算法
对于给定的带权有向图G=(V,G),其源点为s,加权函数为w:E->R,对该图运行Bellman-Ford算法后返回一个布尔值,表明图中是否存在一个从源点可达的负权回路。若存在这样的回路,算法说明该问题无解;若不存在这样的回路,算法将产生最短路径(p[v])及其权值(d[v])。
此算法对所有的边执行|v|-1次松弛操作。经过|v|-1次迭代后,对于s可达的顶点v,都有d[v]=sp(s,v),该算法的时间复杂度为o(VE)。
证明:设v为从s可达的任意顶点,p=<v0,v1,……,vk>是任一条从s到v的最短路径,其中v0=s和vk=v。路径p至多有|v|-1条边,所以k<=|v|-1。在每一次松弛所有边的操作过程中,第i次迭代被松弛的边为(vi-1,vi),由上述的路径松弛性质,可得d[v]=d[vk]=sp(s,v)。/*Bellman_Frod算法求最短路径*/ #include<iostream> #include<vector> #include<fstream> using namespace std; //边类 struct Node { int value;//存储边的终点 int weight;//存储边的权值 Node(){} Node(int value,int weight) { this->value = value; this->weight = weight; } }; vector<vector<Node>> mGraph;//图结构 int
单源点最短路径
最新推荐文章于 2020-08-25 18:34:07 发布
本文介绍了单源最短路径的概念及其性质,并详细讲解了Bellman-Ford算法、有向无环图(DAG)中的单源最短路径算法以及Dijkstra算法。内容涵盖算法原理、代码实现以及算法复杂度分析,帮助读者深入理解这三种经典算法。
摘要由CSDN通过智能技术生成