最短路算法总结

本文详细介绍了求解图中单源最短路径的几种经典算法,包括Bellman-Ford、Dijkstra、Floyd-Warshall和SPFA。针对负权图和负环路进行了讨论,并提供了C/C++实现代码示例,适合理解这些算法的工作原理和应用场合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、负权图

在一个图里每条边都有一个权值(有正有负),如果存在一个环(从某个点出发又回到自己的路径),而且这个环上所有权值之和是负数,那这就是一个负权环,也叫负权回路。存在负权回路的图是不能求两点间最短路的,因为只要在负权回路上不断兜圈子,所得的最短路长度可以任意小。(没有最短路)

单源点的最短路径问题是指:给定一个加权有向图G和源点s,对于图G中的任意一点v,求从s到v的最短路径。

二、最短路

1Bellman-Ford算法

2Dijkstra算法(代码以邻接矩阵为例)    &&   Dijkstra + 优先队列的优化(也就是堆优化)

3floyd-Warshall算法(代码以邻接矩阵为例)

4SPFA(代码以前向星为例)

5BFS求解最短路

最短路径的估计值:我们的源点用s表示。在这里我们用数组dis[N]来存储最短路径,dis[N]数组为源点到其他点的最小距离。那么最最开始的最短路径的估计值也就是对dis[N]的初始化。一般我们的初始化都是初始化为 dis[N]= +∞源点是要初始化为0的,dis[s] = 0,因为s—>s的距离为0;

三、Bellman-Ford

Bellman-Ford算法是求解单源最短路径问题的一种算法。可以判断有无负权回路(若有,则不存在最短路),时效性较好,时间复杂度O(VE)。与Dijkstra算法不同的是,在Bellman-Ford算法中,边的权值可以为负数。设想我们可以从图中找到一个环路(即从v出发,经过若干个点之后又回到v)且这个环路中所有边的权值之和为负。那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去。如果不处理这个负环路,程序就会永远运行下去。而Bellman-Ford算法具有分辨这种负环路的能力。

3.1 Bellman-Ford算法的流程如下:

给定图G(V, E)(其中VE分别为图G的顶点集与边集),源点s

·数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]inf, Distant[s]0

·以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) <Distant[v],则令Distant[v]= Distant[u]+w(u, v)w(u, v)为边e(u,v)的权值;若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;

·为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) <Distant[v]的边,则图中存在负环路,即是说该图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

可知,该算法寻找单源最短路径的时间复杂度为O(V*E)。

3.2 bellman-ford算法求最短路 C/C++

//起点都从1开始,图采用临接矩阵保存

所用数据结构 :

struct node
{
    int u, v, w;//u 为起点,v为终点,w为u—>v的权值
};
node edge[100];

bool Bellman_Ford(int s) 

    for(int i = 1; i <= node_num;i++) //初始化 

        dis[i] =inf; 

    dis[s]=0;

    for(int i = 1; i < node_num; i++) //进行|V|-1次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值