【C++】深入浅出“图”——最短路径算法

【C++】深入浅出“图”——最短路径算法

文章目录

一、Dijkstra算法

最短路径问题是指,从在带权的有向图中从某一顶点出发,找到通往另一顶点的最短路径,“最短”指的是沿路径各边的权值总和最小。

Dijkstra算法是单源最短路径的经典贪心算法,只能用于没有负权的图。它从起点出发,每次选当前距离最小且未确定最短路径的节点,用它去松弛(更新)所有邻接点的最短路径估计值,标记该节点为 “已确定”,重复此过程直到所有节点处理完毕,最终得到起点到图中所有节点的最短路径。

在这里插入图片描述
// src是选定的起点,dist记录起点到各点的最短路径,pPath记录到每个点的最短路径的前驱顶点下标voidDijkstra(const V& src, vector<W>& dist, vector<int>& pPath){ size_t srci =GetVertexIndex(src); size_t n = _vertexs.size(); dist.resize(n, MAX_W); pPath.resize(n,-1); dist[srci]=0; pPath[srci]= srci;// 已经确定最短路径的顶点集合 vector<bool>S(n,false);for(size_t j =0; j < n;++j){// 选最短路径顶点且不在S更新其他路径int u =0; W min = MAX_W;for(size_t i =0; i < n;++i){if(S[i]==false&& dist[i]< min){ u = i; min = dist[i];}} S[u]=true;// 松弛更新u连接顶点v srci->u + u->v < srci->v 更新for(size_t v =0; v < n;++v){if(S[v]==false&& _matrix[u][v]!= MAX_W && dist[u]+ _matrix[u][v]< dist[v]){ dist[v]= dist[u]+ _matrix[u][v]; pPath[v]= u;}}}}

二、Bellman_Ford算法

Bellman_Ford算法能用来解决负权图的单源最短路径问题,但是它的时间复杂度高于Dijkstra算法,本质是暴力求解。从起点出发,把图里所有边从头到尾松弛一遍,重复n次,就能算出起点到所有点的最短路径;因为任何最短路径最多只经过n‑1条边。跑完之后再扫一遍所有边,如果还能更新距离,就说明图里有负权回路,最短路径不存在。

在这里插入图片描述
boolBellmanFord(const V& src, vector<W>& dist, vector<int>& pPath){ size_t n = _vertexs.size(); size_t srci =GetVertexIndex(src);// vector<W> dist,记录srci-其他顶点最短路径权值数组 dist.resize(n, MAX_W);// vector<int> pPath 记录srci-其他顶点最短路径父顶点数组 pPath.resize(n,-1);// 先更新srci->srci为缺省值 dist[srci]=W();// 总体最多更新n轮for(size_t k =0; k < n;++k){// i->j 更新松弛bool update =false; cout <<"更新第:"<< k <<"轮"<< endl;for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// srci -> i + i ->jif(_matrix[i][j]!= MAX_W && dist[i]!= MAX_W && dist[i]+ _matrix[i][j]< dist[j]){ update =true;//cout << _vertexs[i] << "->" << _vertexs[j] << ":" << _matrix[i][j] << endl; dist[j]= dist[i]+ _matrix[i][j]; pPath[j]= i;}}}// 如果这个轮次中没有更新出更短路径,那么后续轮次就不需要再走了if(update ==false){break;}}// 还能更新就是带负权回路for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// srci -> i + i ->jif(_matrix[i][j]!= MAX_W && dist[i]+ _matrix[i][j]< dist[j]){returnfalse;}}}returntrue;}

三、Floyd_Warshall算法

Floyd-Warshall算法是求任意两点之间最短路径的算法,依次把每个点当作中转点,判断从 i 到 j 是直接走更近,还是经过这个中转点 k 再走更近,不断更新所有点对的最短距离,三层循环跑完就得到全图最短路径。

voidFloydWarshall(vector<vector<W>>& vvDist, vector<vector<int>>& vvpPath){ size_t n = _vertexs.size(); vvDist.resize(n); vvpPath.resize(n);// 初始化权值和路径矩阵for(size_t i =0; i < n;++i){ vvDist[i].resize(n, MAX_W); vvpPath[i].resize(n,-1);}// 直接相连的边更新一下for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){if(_matrix[i][j]!= MAX_W){ vvDist[i][j]= _matrix[i][j]; vvpPath[i][j]= i;}if(i == j){ vvDist[i][j]=W();}}}// 最短路径的更新i-> {其他顶点} ->jfor(size_t k =0; k < n;++k){for(size_t i =0; i < n;++i){for(size_t j =0; j < n;++j){// k 作为的中间点尝试去更新i->j的路径if(vvDist[i][k]!= MAX_W && vvDist[k][j]!= MAX_W && vvDist[i][k]+ vvDist[k][j]< vvDist[i][j]){ vvDist[i][j]= vvDist[i][k]+ vvDist[k][j];// 找跟j相连的上一个邻接顶点// 如果k->j 直接相连,上一个点就k,vvpPath[k][j]存就是k// 如果k->j 没有直接相连,k->...->x->j,vvpPath[k][j]存就是x vvpPath[i][j]= vvpPath[k][j];}}}}}

Read more

从零开始:在本地搭建一个带知识库的 AI 助手(Ollama + Open WebUI)

从零开始:在本地搭建一个带知识库的 AI 助手(Ollama + Open WebUI)

一文讲清楚:要选哪些工具、需要什么环境、整体架构长什么样,以及一步步实现到能用的程度。 一、为什么要在本地搭一个 AI 助手? 过去一年,大模型从“新奇玩意儿”迅速变成“日常生产力工具”。但如果你只用网页版 ChatGPT / 文心一言 / 通义千问,会碰到几个很现实的问题: * 数据隐私:公司内部文档、个人笔记、聊天记录,你敢全部塞到线上吗? * 网络依赖:在飞机上、高铁里,或者公司内网严格管控时,在线 AI 直接“失联”。 * 额度与费用:免费额度有限,稍微重度一点就要付费,而且你也不知道自己的数据会不会被拿去训练。 本地部署一套 “AI + 知识库” 的好处就非常直观: 1. 数据完全不出本地,满足隐私合规要求。 2. 断网也能用,随时随地调取你的“第二大脑”。 3. 可定制:可以给团队搭一个“

By Ne0inhk
Flutter for OpenHarmony: Flutter 三方库 sanitize_html 彻底杜绝 XSS 注入风险(鸿蒙 Web 内容安全净化)

Flutter for OpenHarmony: Flutter 三方库 sanitize_html 彻底杜绝 XSS 注入风险(鸿蒙 Web 内容安全净化)

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 在开发 OpenHarmony 应用时,如果我们需要在 UI 中渲染来自后端的 HTML 内容(例如文章正文、用户评论),或者使用 flutter_html 等库,一个致命的安全风险就是 XSS (跨站脚本攻击)。恶意代码可能会通过 <script> 标签或 onerror 属性在你的 App 内执行非法逻辑。 sanitize_html 是一个轻量级且极高效的 HTML 净化库。它采用白名单机制,能瞬间过滤掉所有不安全的标签和属性,确保你在鸿蒙 App 内渲染的每一行 Web 内容都是绝对安全的。 一、核心防御机制解析 sanitize_html 遵循“默认拒绝”

By Ne0inhk

前端保持和服务器时间同步的方法【使用vue3举例】

你只管努力!剩下的交给时间! 目录 * 引言: * 方法一: 轮询(定时请求服务器时间) * 优点: * 缺点: * 方法二:使用WebSocket * 优点: * 缺点: * 方法三:时间戳校正 * 优点: * 缺点: * 方法四: 使用NTP(网络时间协议) * 优点: * 缺点: * 方法五:使用SSE(Server-Sent Events) * 优点: * 缺点: * 总结: 引言: 保持前端与服务器时间同步是一个常见的需求,特别是在需要确保时间一致性的应用中,比如在线投票、实时聊天或游戏等。以下是一些方法来实现这一目标: 方法一: 轮询(定时请求服务器时间) 可以定时向服务器发送请求获取当前时间,以此来更新前端的时间显示。 <template><div><h1>当前时间:

By Ne0inhk
前端异常捕获与统一格式化:从 console.log(error) 到服务端上报

前端异常捕获与统一格式化:从 console.log(error) 到服务端上报

🧑 博主简介:ZEEKLOG博客专家,「历代文学网」(公益文学网,PC端可以访问:https://lidaiwenxue.com/#/?__c=1000,移动端可关注公众号 “ 心海云图 ” 微信小程序搜索“历代文学”)总架构师,首席架构师,也是联合创始人!16年工作经验,精通Java编程,高并发设计,分布式系统架构设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s,热衷于探索科技的边界,并将理论知识转化为实际应用。保持对新技术的好奇心,乐于分享所学,希望通过我的实践经历和见解,启发他人的创新思维。在这里,我希望能与志同道合的朋友交流探讨,共同进步,一起在技术的世界里不断学习成长。 🤝商务合作:请搜索或扫码关注微信公众号 “ 心海云图 ” 前端异常捕获与统一格式化:从 console.log(error) 到服务端上报 引言 在前端开发中,异常监控是保证应用稳定性的重要一环。当用户遇到页面白屏、功能不可用等问题时,如果能及时收集到详细的错误信息(包括堆栈、

By Ne0inhk