最短路径 Shortest Path

本文详细介绍了最短路径问题,包括最短路径树的概念,以及Dijkstra算法、Floyd-Warshall算法和Bellman-Ford算法的原理、步骤和应用。Dijkstra适用于非负权重,Floyd-Warshall求解全源最短路径,Bellman-Ford能处理负权重边并检测负环。
摘要由CSDN通过智能技术生成

来自我的博客最短路径 Shortest Path - Snow’s Blog (ivansnow02.github.io)

最短路径 Shortest Path

加权有向图中每条路径都有值,其值是该路径上所有边的权值之和。最短路径 (Shortest Path)问题就是指求出两个给定顶点间权值最小的路径。

定义

两个顶点s和t之间的一条最短路径 是从s到t的一条有向简单路径,而且此路径 具有以下的性质:不存在另一条这样的路径且有更小的权值。

最短路径树(Shortest-path trees, 简称SPT)

给定一个图和一个指定的顶点s,则s的最短路径树是一个包含s以及由s可达的所有顶点的子图,它构成以s为根的一棵有向树,其中每条树路径都是图中的一条最短路径。最短路径树定义了从根到其它顶点的最短路径。

分类

图中最短路径问题主要是以下三类:

  1. 源点-汇点最短路径
  2. 单源最短路径
  3. 全源最短路径

算法

求图中最短路径的算法常用的有:

  1. Dijkstra算法
  2. Floyd-Warshall算法
  3. Bellman-Ford算法

### 基本操作

边松弛(edge relaxation)

检查一条给定的边,是否可以通过该边,对到其所指顶点的最短路径进行更新。

不妨设有条边e=(u,v),它的长度是e.distd[i]表示源点到顶点i的最短距离,则松弛操作如下: if (d[v] > d[u] + e.dist) d[v] = d[u] + e.dist 上式的意思就是:如果从源点到u的最短距离加上u到v的长度小于当前源点到v的最短距离,那么更新源点到v的最短距离。 边松弛体现在Dijkstra算法和Bellman-Ford算法中

路径松弛(path relaxation)

检查一个给定顶点,是否可以使得连接另外两个给定顶点的最短路径进行更新。

不妨设现在有一个顶点x,还有另外两个顶点s和t。考虑能否通过x,使得s到t的最短距离变的更小,能的话,就进行路径松弛:if (d[s][t] > d[s][x] + d[x][t]) d[s][t] = d[s][x] + d[x][t]上式的意思是:如果s到x的最短距离加上x到t的最短距离小于s到t的最短距离,那么更新s到t的最短距离。路径松弛体现在Floyd-Warshall算法中。

Dijkstra算法

Dijkstra算法计算单源最短路径,它的基本思想:开始把源点放在SPT中,然后,每次增加一条边来构造SPT,所取的边总是可以给出从源点到尚未在SPT中的一个顶点的最短路径。也就是说,按照顶点与起始顶点的距离(通过SPT)为顺序来加入顶点。即:每次选不在SPT中距离源点最近的点加
入SPT。

具体步骤

  1. 初始化:顶点集S只包含源点,即S={v},顶点集U包含除v外的其他顶点。
  2. 从U中选取一个顶点u,它是源点v到U中最短路径长度最小的顶点,然后把顶点u加入S中(此时求出了源点v到顶点u的最短路径长度)。
  3. 以顶点u为新考虑的中间点,修改顶点u的出边邻接点j的最短路径长度,此时源点v到顶点j的最短路径有两条,即一条经过顶点u,一条不经过顶点u。
  4. 重复步骤2和3,直到S包含所有的顶点即U为空。

基于堆的Dijkstra算法代码

struct Edge {
   
    int from, to, dist;
    Edge(int u, int v, int d) : from(u), to(v), dist(d) {
   }
};
struct HeapNode {
    
    int d, u; // d表示该点到源点的距离,u是该点的编号
    bool operator< (const HeapNode& rhs) const {
   
        return d > rhs.d; 
    } // 小根堆
};
vector<Edge> edges; // edges存所有的边的信息
vector<int> G[MAXN]; // G[i]是顶点i发出的所有边
bool done[MAXN]; // 是否已经加入SPT
int d[MAXN]; // 每个点到源点的最短路径
int p[MAXN]; // 记录到顶点i的是哪条边
void Dijkstra(int s, int V) {
    // 计算所有顶点到顶点s的最短路径
    priority_queue<HeapNode> Q;
    for(int i = 0; i < V; ++i) d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值