算法-最短路径

图的最短路径问题是一个经典的计算机科学和运筹学问题,旨在找到图中两个顶点之间的最短路径。这种问题在多种场景中都有应用,如网络路由、地图导航等。

解决图的最短路径问题有多种算法,其中最著名的包括:
1.迪杰斯特拉算法
(1). 图的要求
适用于权重非负的图。
(2). 实现
该算法的实现通常包括以下步骤:
a. 初始化:将源节点标记为最短路径已经知道.设置其路径距离为0.将其入队列.
b. 循环迭代,直到队列为空
b.1. 出队列,得p
b.2.迭代&更新.
即对从p可达,且最短路径尚未确定节点q
比较,若p的路径距离+Edge<p,q>小于q的路径距离,则更新q的路径距离=p的路径距离+Edge<p,q>.设置p为其路径上一节点.
b.3.从最短路径尚未确定节点中选出路径值最小节点t.将t的最短路径标记为已经知道.t入队列.在无法选出这样的t时,表示剩余节点均不可达.可提前结束迭代.

(3). 实例
在这里插入图片描述
(4). 算法实现

#define MAX 0x7fffffff
class NodeInfo{
public:char m_nName;int32_t m_nPath = MAX;int32_t m_nPreIndex = -1;int32_t m_nTag = -1;
};template<class T>
class Node{
public:T m_nEle;
};template<class EdgeInfo>
class Edge{
public:int32_t m_nWeight = MAX;bool m_bValid = false;
};Node<NodeInfo> stNodes[7];
Edge<int> stEdges[7][7];
void Sort(void* lpBegin, void *lpEnd);
int main(){stNodes[0].m_nEle.m_nName = 'A';stNodes[1].m_nEle.m_nName = 'B';stNodes[2].m_nEle.m_nName = 'C';stNodes[3].m_nEle.m_nName = 'D';stNodes[4].m_nEle.m_nName = 'E';stNodes[5].m_nEle.m_nName = 'F';stNodes[6].m_nEle.m_nName = 'G';stEdges[0][1].m_nWeight = 1;stEdges[0][1].m_bValid = true;stEdges[1][0].m_bValid = true;stEdges[1][0].m_nWeight = 1;stEdges[0][4].m_bValid = true;stEdges[0][4].m_nWeight = 2;stEdges[4][1].m_bValid = true;stEdges[4][1].m_nWeight = 2;stEdges[1][3].m_bValid = true;stEdges[1][3].m_nWeight = 1;stEdges[1][5].m_bValid = true;stEdges[1][5].m_nWeight = 4;stEdges[4][3].m_bValid = true;stEdges[4][3].m_nWeight = 2;stEdges[3][2].m_bValid = true;stEdges[3][2].m_nWeight = 1;stEdges[3][6].m_bValid = true;stEdges[3][6].m_nWeight = 2;stEdges[2][6].m_bValid = true;stEdges[2][6].m_nWeight = 2;int nSourceIndex = 0;stNodes[nSourceIndex].m_nEle.m_nTag = 1;stNodes[nSourceIndex].m_nEle.m_nPath = 0;stNodes[nSourceIndex].m_nEle.m_nPreIndex = -1;int32_t nArrQueue[7];int32_t nFirst = 0;int32_t nEnd = 0;int32_t nNum = 0;nArrQueue[0] = nSourceIndex;nFirst = 0;nEnd = 1;nNum = 1;while(nNum > 0){// 出队列int32_t nIndex;if(nNum = 1){nIndex = nArrQueue[nFirst];nFirst = 0;nEnd = 0;nNum = 0;}else{nIndex = nArrQueue[nFirst];nFirst = (nFirst+1)%7;nNum--;}// 迭代&更新for(int32_t i = 0; i < 7; i++){if(stEdges[nIndex][i].m_bValid && stNodes[i].m_nEle.m_nTag == -1){if(stNodes[i].m_nEle.m_nPath > stNodes[nIndex].m_nEle.m_nPath + stEdges[nIndex][i].m_nWeight){stNodes[i].m_nEle.m_nPath = stNodes[nIndex].m_nEle.m_nPath + stEdges[nIndex][i].m_nWeight;stNodes[i].m_nEle.m_nPreIndex = nIndex;}}}// 入队列// 选择未访问节点中最短距离最小的一个nIndex = -1;int32_t nMin = MAX;for(int32_t i = 0; i < 7; i++){if(stNodes[i].m_nEle.m_nTag == -1 && stNodes[i].m_nEle.m_nPath < nMin){nMin = stNodes[i].m_nEle.m_nPath;nIndex = i;}}if(nIndex == -1){break;// 所有节点均已被访问.或剩余节点全部不可达.}// 选举的节点就是最短路径已知的stNodes[nIndex].m_nEle.m_nTag = 1;if(nNum == 0){nArrQueue[0] = nIndex;nFirst = 0;nEnd = 1;nNum++;}else{nArrQueue[nEnd] = nIndex;nEnd = (nEnd+1)%7;nNum++;}}// testprintf("finish\n");while(true){int32_t nIndex = -1;scanf("%d", &nIndex);getchar();printf("path_%d\n", stNodes[nIndex].m_nEle.m_nPath);printf("%c ", stNodes[nIndex].m_nEle.m_nName);while(nIndex != -1){printf("%c ", stNodes[stNodes[nIndex].m_nEle.m_nPreIndex].m_nEle.m_nName);nIndex = stNodes[nIndex].m_nEle.m_nPreIndex;}printf("\n");}return 0;
}

2.贝尔曼-福特算法(Bellman-Ford Algorithm):
(1). 图的要求
可以处理带有负权重的图,但无法处理包含负权重环的图。
针对权重为负的图,可以让所有边权中加上一个基础量转变为权重非负的,再通过迪杰斯特拉求解.所以,正常没必要用这个.
时间复杂度为O(|V|*|E|)

(2). 算法
贝尔曼-福特算法(Bellman-Ford Algorithm)的实现过程可以分为以下三个阶段:

a. 初始化阶段:
创建一个数组Distant,用于记录从源点s到图中各个顶点的最短路径长度估计值。通常,将源点s到自己的距离Distant[s]初始化为0,而将源点s到其他所有顶点的距离初始化为一个较大的值(如无穷大),表示这些顶点与源点之间的最短路径尚未确定。
b. 松弛操作阶段:
这个阶段需要进行|V|-1次迭代,其中V是图中顶点的数量。在每一次迭代中,遍历图中的所有边(u, v),并检查是否可以通过这条边来更新从源点s到顶点v的最短路径长度估计值。
具体来说,对于每一条边(u, v),如果Distant[u] + w(u, v) < Distant[v],则更新Distant[v]Distant[u] + w(u, v)。这里,w(u, v)是边(u, v)的权重,表示从顶点u到顶点v的距离或成本。
通过不断的松弛操作,Distant数组中的值会逐渐逼近从源点到各个顶点的实际最短路径长度。
c. 负权回路检测阶段:
在完成|V|-1次松弛操作后,再进行一次额外的松弛操作。这次操作的目的是为了检测图中是否存在负权回路(即从某个顶点出发,经过一系列边后回到该顶点,且整个回路的总权重为负)。
如果在额外的松弛操作中,仍然有Distant数组的值被更新,那么就说明图中存在负权回路。因为负权回路的存在会导致最短路径问题无解,因为可以通过不断绕行负权回路来减小路径长度。
如果额外的松弛操作没有更新Distant数组的值,那么算法结束,Distant数组中存储的就是从源点到各个顶点的最短路径长度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/767370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NIO详解

前期处理 对应的思维导图地址: https://www.processon.com/view/link/62247e810e3e74108ca1b5d7 对应的 Github地址: https://github.com/yuejianli/NIO 依赖 全局 pom.xml 依赖 <dependencies><dependency\><groupId\>junit</groupId\><artif…

AWTK T9 输入法实现原理

1. T9 输入法的中文字典数据 网上可以找到 T9 输入法的中文字典数据&#xff0c;但是通常有两个问题&#xff1a; 采用 GPL 协议&#xff0c;不太适合加入 AWTK。 只支持单个汉字的输入&#xff0c;不支持词组的输入。 经过考虑之后&#xff0c;决定自己生成 T9 输入法的中…

Mamba复现与代码解读

文章目录 环境配置demo推理源码解析参数解读Mamba块&#xff08;Mamba Block&#xff09;状态空间模型(SSM)选择性扫描算法&#xff08;selective_scan&#xff09;前向传播&#xff08;forward&#xff09; 均方根归一化 &#xff08;RMSNorm&#xff09;残差块&#xff08;Re…

集成学习 | 集成学习思想:Boosting

目录 一. Boosting思想1. Adaboost 算法1.1 Adaboost算法构建流程1.2 sklearn库参数说明 2. Gradient Boosting 算法2.1 Gradient Boosting算法构建流程2.2 Gradient Boosting算法的回归与分类问题2.2.1 Gradient Boosting回归算法均方差损失函数绝对误差损失函数 2.2.2 Gradie…

CAS(Compare-And-Swap)机制介绍

一、概念介绍 CAS&#xff08;Compare-And-Swap&#xff09;机制在C中是一种用于实现并发编程中同步和互斥的重要技术。CAS机制提供了一种原子操作&#xff0c;允许程序在不使用锁的情况下对共享变量进行读取、修改和写入。这种机制的核心思想是先比较再设置&#xff0c;即在修…

理论学习:ground-truth labels在深度学习中是什么意思

在深度学习中&#xff0c;"ground-truth labels"&#xff08;真值标签&#xff09;是指数据集中每个样本的正确答案或真实状态。这些标签是由人类专家提供的&#xff0c;代表了我们希望模型学习预测的准确结果。在训练深度学习模型时&#xff0c;真值标签被用作参照点…

【Linux】进程地址空间详解

前言 在我们学习C语言或者C时肯定都听过老师讲过地址的概念而且老师肯定还会讲栈区、堆区等区域的概念&#xff0c;那么这个地址是指的物理内存地址吗&#xff1f;这里这些区域又是如何划分的呢&#xff1f; 我们在使用C语言的malloc或者C的new函数开辟空间时&#xff0c;开辟…

Median of an Array(贪心策略,编程技巧)

文章目录 题目描述输入格式输出格式样例输入样例输出提交链接提示 解析参考代码 题目描述 给你一个由 n n n 个整数组成的数组 a a a 。 数组 q 1 , q 2 , … , q k q_1,q_2,…,q_k q1​,q2​,…,qk​ 的中位数是 p ⌈ k 2 ⌉ p⌈\frac {k}{2}⌉ p⌈2k​⌉ &#xff0c;其…

可解释性AI(XAI)

可解释性AI&#xff08;XAI&#xff09;旨在提高人工智能系统的透明度和可理解性&#xff0c;使人们更好地理解AI的决策过程和原理。随着AI技术的广泛应用&#xff0c;XAI成为了一个备受关注的重要领域。它不仅有助于建立人们对AI的信任&#xff0c;还可以帮助解决AI伦理和偏见…

解锁隐私计算力量:一站式掌握SecretFlow安装与双模式部署实践

1.SecretFlow的安装 1.SecretFlow运行要求 SecretFlow作为一个隐私保护的数据分析和机器学习框架&#xff0c;其运行要求可能涉及以下方面&#xff1a; 操作系统&#xff1a; 能够支持Docker运行的环境&#xff0c;因为SecretFlow可能通过Docker容器来管理执行环境的一致性和…

Python Flask 自定义404错误

from flask import Flask, abort, make_response, request, render_templateapp Flask(__name__)# 重定向到百度 app.route(/index, methods["GET", "POST"]) def index():if request.method "GET":return render_template("index.html&q…

敏捷开发最佳实践:组织架构实践案例之构建软硬件融合部落

本节所选案例对于软硬件均有的企业具有重要借鉴意义&#xff0c;通过学习某一线制造行业合资企业如何解决软硬件部门之间的技术鸿沟和部门墙&#xff0c;以及全球分布的多支敏捷团队的协作难题&#xff0c;为所在企业在“组织架构”层面进行有效敏捷实践打开思路。 本实践节选…

推荐一款制造执行系统(MES)国内比较好的实施厂家

什么是MES 制造执行系统&#xff08;MES&#xff09;是一种用于监控、控制和优化制造过程的软件系统。它通过与企业资源计划&#xff08;ERP&#xff09;系统和自动化系统的集成&#xff0c;实现对生产过程的管理和监测&#xff0c;包括生产计划、生产过程和生产数据。 MES可…

小白入门赛8

小白入门赛8 1 #include<bits/stdc.h> using namespace std;int main(){puts("5060");return 0; } 2 只考虑两个字符串a&#xff0c;b的情况下&#xff0c;优先让 a b ab ab 或 b a ba ba 中最小的放前面&#xff0c;据此排序 int n; string s[200010]…

BUG未解之谜01-指针引用之谜

在leetcode里面刷题出现的问题&#xff0c;当我在sortedArrayToBST里面给root赋予初始值NULL之后&#xff0c;问题得到解决&#xff01; 理论上root是未初始化的变量&#xff0c;然后我进入insert函数之后&#xff0c;root引用的内容也是未知值&#xff0c;因此无法给原来的二叉…

鸿蒙开发学习【地图位置服务组件】

简介 移动终端设备已经深入人们日常生活的方方面面&#xff0c;如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动&#xff0c;都离不开定位用户终端设备的位置。 当用户处于这些丰富的使用场景中时&#xff0c;系统的位置定位能力可以提供…

map 添加 访问 遍历

#include<iostream> #include<vector> #include<set> #include<map> using namespace std; int main() { //创建 map<string, int>m; //添加 m["hello"] 2; m["ijii"] 1; //访问 如果存在返回值,不…

[HackMyVM]靶场 Submissions

kali:192.168.56.104 靶机:192.168.56.131 端口扫描 # nmap 192.168.56.131 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-24 11:32 CST Nmap scan report for 192.168.56.131 Host is up (…

【Python】基础语法(一)

文章目录 1.注释2.关键字与标识符2.1关键字2.2标识符 3.变量4.数据类型4.1数字类型4.2类型转换函数4.3布尔类型 5.输入(input)与输出(print)5.1输入函数(input)5.2输出函数(print) 6.运算符6.1算术运算符6.2比较运算符6.3赋值运算符6.4逻辑运算符6.5运算符优先级 7.字符串7.1字…

JMH微基准测试框架学习笔记

一、简介 JMH&#xff08;Java Microbenchmark Harness&#xff09;是一个用于编写、构建和运行Java微基准测试的框架。它提供了丰富的注解和工具&#xff0c;用于精确控制测试的执行和结果测量&#xff0c;从而帮助我们深入了解代码的性能特性。 二、案例实战 在你的pom文件…