贝尔曼福特算法——负权值单源最短路径

这篇具有很好参考价值的文章主要介绍了贝尔曼福特算法——负权值单源最短路径。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


title: 贝尔曼福特算法——负权值单源最短路径
date: 2023-05-16 11:42:26
tags: 数据结构与算法


  • 贝尔曼福特算法——负权值单源最短路径

    **问题:**具有负权值非环图的单源最短路径算法

    git地址:https://github.com/944613709/HIT-Data-Structures-and-Algorithms

    算法思想:

    对图中的边进行V-1轮遍历,对所有的边松弛(对每条边v1->v2,如果d[v2]+Weight(v1->v2)<d[v2]就更新d[v2]),利用上述遍历松弛可以得到最终最短路径,和再次松弛判断有无负权值环(遍历都结束后,若再进行一次遍历,还能得到到某些节点更短的路径的话,则说明存在负环路)

    算法步骤:

    0. 建立图

    1. 初始化d,如果s->v1有边,则d[v1]=G.ENode[s][v2],并且path设为s的下标,而d[s]=0;

    *2.*对图进行V-1次松弛

    1.1**每一次松弛,就是去遍历图的所有边,如果可以做到d[v1]+G.ENode[v1][v2] (v1->v2的weight) <d[v2],就更新d[v2]

    *3.*再次进行遍历松弛,如果还能得到新的d的值,则代表存在负环路(环上权值和<0)

    测试样例:

    权值为负数的最短路径,数据结构与算法,算法,图论,数据结构

    权值为负数的最短路径,数据结构与算法,算法,图论,数据结构

    具体代码

    **文章来源地址https://www.toymoban.com/news/detail-623534.html

    - #include<bits/stdc++.h>**
    
      **#define MaxVerNum 100 //****顶点最大数目值**
    
      **#define INF 0x3f3f3f3f//****作为最大值**
    
      **using namespace std;**
    
      **//****图的数据结构**
    
      **typedef struct Graph**
    
      **{**
    
      ​     **char VNode[MaxVerNum];//****顶点表**
    
      ​     **int ENode[MaxVerNum][MaxVerNum];//****弧表**
    
      ​     **int numVNode, numARC;//****顶点数、弧数**
    
      **}Graph;**
    
      **int D[MaxVerNum]; //****到各个顶点的最短路径**
    
      **int Path[MaxVerNum]; //****记录前驱**
    
      **void InitGraph(Graph &G)**
    
      **{**
    
      ​     **memset(G.VNode, '#', sizeof(G.VNode));//****初始化顶点表**
    
      ​                                           **//****初始化弧表**
    
      ​     **for (int i = 0; i < MaxVerNum; i++)**
    
      ​          **for (int j = 0; j < MaxVerNum; j++)**
    
      ​              **G.ENode[i][j] = INF;**
    
      ​     **G.numARC = G.numVNode = 0;     //****初始化顶点数、弧数**
    
      **}**
    
      **bool InsertNode(Graph &G, char v)**
    
      **{**
    
      ​     **if (G.numVNode < MaxVerNum)**
    
      ​     **{**
    
      ​          **G.VNode[G.numVNode++] = v;**
    
      ​          **return true;**
    
      ​     **}**
    
      ​     **return false;**
    
      **}**
    
      **bool InsertENode(Graph &G, char v, char w, int weight)**
    
      **{**
    
      ​     **int p1, p2;//v,w****两点下标**
    
      ​     **p1 = p2 = -1;//****初始化**
    
      ​     **for (int i = 0; i<G.numVNode; i++)//****寻找顶点下标**
    
      ​     **{**
    
      ​          **if (G.VNode[i] == v)p1 = i;**
    
      ​          **if (G.VNode[i] == w)p2 = i;**
    
      ​     **}**
    
      ​     **if (-1 != p1&&-1 != p2)//****两点均可在图中找到**
    
      ​     **{**
    
      ​          **G.ENode[p1][p2] = weight;//****有向图邻接矩阵不对称**
    
      ​          **G.numARC++;**
    
      ​          **return true;**
    
      ​     **}**
    
      ​     **return false;**
    
      **}**
    
      **void Bellman_Ford(Graph G, int v)**
    
      **{**
    
      ​     **//****初始化**
    
      ​     **int n = G.numVNode;//n****为图的顶点个数**
    
      ​     **for (int i = 0; i < n; i++)**
    
      ​     **{**
    
      ​          **D[i] = G.ENode[v][i];**
    
      ​          **if (D[i] < INF)Path[i] = v;**
    
      ​          **else Path[i] = -1;**
    
      ​     **}**
    
      ​     **D[v] = 0;**
    
      ​     **for(int i=0;i<G.numVNode-1;i++)**
    
      ​          **for(int j=0;j<G.numVNode;j++)**
    
      ​              **for(int k=0;k<G.numVNode;k++)** 
    
      ​                   **if (D[k] > D[j] + G.ENode[j][k])**
    
      ​                   **{**
    
      ​                        **D[k] = D[j] + G.ENode[j][k];**
    
      ​                        **Path[k] = j;**
    
      ​                   **}**
    
      ​     **bool flag = true;**
    
      ​     **for (int j = 0; j<G.numVNode - 1; j++)** 
    
      ​          **for (int k = 0; k<G.numVNode - 1; k++)** 
    
      ​              **if (D[k] > D[j] + G.ENode[j][k])**
    
      ​              **{**
    
      ​                   **flag = false;**
    
      ​                   **break;**
    
      ​              **}**
    
      ​          **if(flag == false)**
    
      ​     **{**
    
      ​          **cout << "****有负圈错误" << endl;**
    
      ​          **exit(0);**
    
      ​     **}**
    
      ​     **for(int i=0;i<n;i++)**
    
      ​     **{**
    
      ​          **cout<<"****顶点"<<G.VNode[i]<<" ";**
    
      ​          **cout<<"D["<<i<<"]"<<"="<<D[i]<<" ";**
    
      ​          **cout<<"Path["<<i<<"]="<<Path[i];**
    
      ​          **cout<<endl;**
    
      ​     **}**
    
       
    
      **}**
    
      **void CreateGraph(Graph &G) //****读入边和顶点建立邻接矩阵** 
    
      **{**
    
      ​     **FILE \*p;**
    
      ​     **assert((p=fopen("MatGraph.txt","r"))!=NULL);**
    
      ​     **int n;**
    
      ​     **fscanf(p,"****顶点个数=%d;",&n);**
    
      ​     **for(int i=0;i<n;i++)**
    
      ​     **{**
    
      ​          **char V;**
    
      ​          **fscanf(p,"%c;",&V);**
    
      ​          **if (InsertNode(G, V)) continue;//****插入点**
    
      ​          **else {**
    
      ​              **cout << "****输入错误!" << endl; break;**
    
      ​          **}**
    
      ​     **}**
    
      ​     **int m;**
    
      ​     **char flag;**
    
      ​     **fscanf(p,"****边个数=%d;",&m);**
    
      ​     **for(int i=0;i<m;i++)**
    
      ​     **{**
    
      ​          **char V1,V2;**
    
      ​          **int weight;**
    
      ​          **fscanf(p,"%c,%c,%d;",&V1,&V2,&weight);**
    
      ​              **if(InsertENode(G,V1,V2,weight))**
    
      ​        **continue;**
    
      ​     **}**
    
      ​     **fclose(p);**
    
      ​     **cout << "****图的顶点及邻接矩阵:" << endl;**
    
      ​     **for (int i = 0; i < G.numVNode; i++)**
    
      ​     **{**
    
      ​          **cout << G.VNode[i] << " ";**
    
      ​     **}**
    
      ​     **cout << endl;**
    
      ​          **for (int i = 0; i < G.numVNode; i++)**
    
      ​     **{**
    
      ​          **for (int j = 0; j < G.numVNode; j++)**
    
      ​          **{**
    
      ​              **if (G.ENode[i][j] == INF)cout << "∞ ";**
    
      ​              **else cout << G.ENode[i][j] << " ";**
    
      ​          **}**
    
      ​          **cout << endl;**
    
      ​     **}**
    
      **}**
    
       
    
      **int main()**
    
      **{**
    
      ​     **Graph G;**
    
      ​     **InitGraph(G);**
    
      ​     **CreateGraph(G);**
    
      ​     **char V;**
    
      ​     **int v = -1;**
    
      ​     **cin >> V;**
    
      ​     **for (int i = 0; i < G.numVNode; i++)**
    
      ​          **if (G.VNode[i] == V)**
    
      ​              **v = i;**
    
      ​     **if (v == -1)**
    
      ​     **{**
    
      ​          **cout << "ERROR" << endl;**
    
      ​          **return 0;**
    
      ​     **}**
    
      ​     **Bellman_Ford(G,v);**
    
      **}**
    
    
    

到了这里,关于贝尔曼福特算法——负权值单源最短路径的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 强化学习从基础到进阶-常见问题和面试必知必答[2]:马尔科夫决策、贝尔曼方程、动态规划、策略价值迭代

    马尔可夫性质(Markov property,MP) :如果某一个过程未来的状态与过去的状态无关,只由现在的状态决定,那么其具有马尔可夫性质。换句话说,一个状态的下一个状态只取决于它的当前状态,而与它当前状态之前的状态都没有关系。 马尔可夫链(Markov chain) : 概率论和数

    2024年03月26日
    浏览(52)
  • 【算法】单源最短路径算法——Dijkstra算法

    迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。这是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用 贪心算法 的策略, 每次遍历到始点距离最

    2024年02月05日
    浏览(46)
  • 图论算法基础:单源最短路径Dijkstra算法分析

    在 有向带权图 中给定一个起始顶点(源点),Dijkstra算法可以求出 所有其他顶点 到源点的最短路径,Dijkstra算法 不能用于同时含有正负权值的边的图 Source 顶点集合:已经确定 到源点的最短路径 的顶点就会加入 Source 集合中, Source 集合初始时只有源点 dist 数组:用于记录每个顶点到

    2024年02月11日
    浏览(44)
  • 数据结构学习记录——图-最短路径问题(无权图单源最短路径算法、有权图单源最短路径算法、多源最短路径算法、Dijkstra(迪杰斯特拉)算法、Floyd算法)

    目录 问题分类  无权图单源最短路径算法 思路 伪代码 时间复杂度 代码实现(C语言) 有权图单源最短路径算法 Dijkstra(迪杰斯特拉)算法 伪代码  时间复杂度  代码实现(C语言) 多源最短路径算法 两种方法 Floyd算法 代码实现(C语言) 最短路径问题的抽象 在网络中,求

    2024年02月08日
    浏览(59)
  • C++算法:单源最短路径Dijkstra

    如果你有一份北京地图,想从中关村走到三元桥,那么怎样能找出实现这一目的的最短路径呢?一种可能的方法就是将这两点之间所有的路线都找出来,然后求出每条路线的距离,找出最短的路线。但是仔细想想我们就会发现这种办法几乎是不可行的,因为这样的路线太多了,

    2024年02月09日
    浏览(45)
  • 算法提高-图论-单源最短路的扩展应用

    多源点单终点最短路建图: 创建虚拟源点(创建虚拟源点的时候以是spfa为例 可以在建图的时候建出来,也可以在spfa这直接入队,也是虚拟源点的意思) 反向建图变成单源点多终点,然后遍历终点的dist即可找出最短路 这题挺简单的就不详细说了,主要是第一次遇到计数问题

    2024年02月16日
    浏览(48)
  • 算法提高-图论-单源最短路的综合应用

    多次dijkstra求每个点到其它点的最短距离, 此时相当于建好了一张图,每个点之间的最短距离都知道了,接下来dfs搜一下怎么走最短即可 一篇博客解释了为什么一个正向建图求最小值,反向建图求最大值 根本思想是保证1到n的买卖是连通的

    2024年02月11日
    浏览(75)
  • 迪杰斯特拉算法 – 图的单源最短路径

    迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。迪杰斯特拉算法采

    2024年02月05日
    浏览(42)
  • 【算法入门&搜索法】走迷宫|单源最短路径1

    ✅作者简介:热爱后端语言的大学生,CSDN内容合伙人 ✨精品专栏:C++面向对象 🔥系列专栏:算法百炼成神 本专栏收录的均为牛客网的算法题目,内含链表、双指针、递归、动态规划、基本数据结构等算法思想的具体运用。牛客网不仅有大量的经典算法题目,也有大厂的面

    2024年02月03日
    浏览(66)
  • 算法提高-图论-单源最短路的建图方式

    建图 找出一个牧场,它到其他牧场的距离之和最小 我是这么理解的,djsktra是一个贪心的思想,加法里面不能加负数我就不说了 求乘法最大值的时候为什么边权必须0-1,因为在乘法最大值里面有一个边权大于1的话那不就等价于求加法最小值的时候有一个边权为负数的么,d

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包