这个算法不能处理负边情况,有负边,请转到Floyd算法或SPFA算法(SPFA不能处理负环,但能判断负环)

SPFA(SLF优化):https://www.cnblogs.com/yifan0305/p/16391419.html

代码很长,耐下心来看完,存储方法为链式前向星存储。

(如果内存放得下的话,建议稠密图用邻接矩阵(或者跑floyd),稀疏图用邻接表,只是建议)

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt;//cnt 计数器 有cnt条边(从1开始存)
struct edge
{
int u,v,w,nxt;
/*u 起点 (不需要的话可以删掉)
v 目标点 w 边权
nxt 指向这条边的上一条边的标号(上一条边是从同一起点发出的边,不要搞混了) */
};
edge e[20020];
int h[2010];//存储第x个点发出的最后一条边的编号
struct nod//存储点
{
int s,w;//s 这个点的标号 w 起点到这个点的最短路径值
};
struct cmp//结构体的比较函数(优先队列要用,看不懂去搜一下,毕竟这里不是它的主场)
{
bool operator()(nod a,nod b)
{
return a.w<b.w;
}
};
nod dis[2010];//存点(毕竟不好处理点的标号和最短路径值相匹配,如果你有更好的方法,忽略这种存法)
bool f[2010];// 标记点是否被染色(看不懂染色的往下看。。。懒得再敲一遍了)
priority_queue<nod,vector<nod>,cmp> q;//定义一个优先队列(存点)
void add(int,int,int);
void dij()//堆优化
{
for(int i=1;i<=n;++i)//初始化
{
dis[i].s=i;//将编号输入
dis[i].w=0x3f3f3f;//将值设为一个很大的值,理由是便于后续使用(废话)
}
dis[1].w=0;//起点到起点的距离是0(该题起点为1,根据题目来)
q.push(dis[1]);//该点入队
while(!q.empty())
{
nod top=q.top();//取出队首元素
int u=top.s,w=top.w;//u 该点的编号 w 起点到点u的最短路径值
f[u]=1;//标记已经被染过色了
//(染色不懂,就理解为这个点已经用过了,标记一下,不能再用了,跟搜索回溯的原理差不多)
q.pop();//出队
for(int i=h[u];i;i=e[i].nxt)//邻接表遍历
{
int v=e[i].v;//v 目标点
if(dis[v].w>w+e[i].w)//松弛操作
{
dis[v].w=w+e[i].w;//更新起点到点v的最短路径值
q.push(dis[v]);//入队
}
if(f[v]) continue;//如果已被染色(看不懂按上面的理解),跳过
//这里松弛和染色不会冲突,松弛操作是更新最优值,染色是为了防止后面扫到该点的非优值(2022.5.15修改)
}
}
}
int main()
{
scanf("%d%d",&n,&m);//输入,根据题目来
for(int a,b,c,i=1;i<=m;++i)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);//加边
add(b,a,c);//加边,如果是有向图,忽略这一步操作
}
dij();//调用函数
if(dis[n].w>=0x3f3f3f-1) printf("-1");
//这里是输出操作,如果起点到点n的值大于0x3f3f3f-1,就说明压根就没更新到,也说明起点和点n不连接
//(题目要求,根据题目来)
else printf("%d",dis[n].w);
return 0;
}
void add(int u,int v,int w)//加边操作
{
e[++cnt].v=v;//记录该条边的目标点
e[cnt].w=w;//记录边权
e[cnt].nxt=h[u];//记录上一条边
h[u]=cnt;//更新从点u发出的最后一条边的边号
}

重载运算符版本

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,g;//cnt 计数器 有cnt条边(从1开始存)s起点
struct edge
{
int u,v,w,nxt;
/*u 起点 (不需要的话可以删掉)
v 目标点 w 边权
nxt 指向这条边的上一条边的标号(上一条边是从同一起点发出的边,不要搞混了) */
};
edge e[20020];
int h[2010];//存储第x个点发出的最后一条边的编号
struct nod//存储点
{
int s,w;//s 这个点的标号 w 起点到这个点的最短路径值
bool operator < (const nod &a) const
{
return w>a.w;
}//运算符重载
};
nod dis[2010];//存点(毕竟不好处理点的标号和最短路径值相匹配,如果你有更好的方法,忽略这种存法)
bool f[2010];// 标记点是否被染色
priority_queue<nod> q;//定义一个优先队列(存点)
void add(int,int,int);
void dij()//堆优化
{
memset(f,0,sizeof f);//初始化数组
for(int i=1;i<=n;++i)//初始化
{
dis[i].s=i;//将编号输入
dis[i].w=0x3f3f3f;//将值设为一个很大的值
}
dis[g].w=0;//起点到起点的距离是0
q.push(dis[g]);//该点入队
while(!q.empty())
{
nod top=q.top();//取出队首元素
int u=top.s,w=top.w;//u 该点的编号 w 起点到点u的最短路径值
q.pop();//出队
if(f[u]) continue;//如果该点已经染过色了,跳过
f[u]=1;//染色
for(int i=h[u];i;i=e[i].nxt)//邻接表遍历
{
int v=e[i].v;//v 目标点
if(!f[v]&&dis[v].w>w+e[i].w)//松弛操作
{
dis[v].w=w+e[i].w;//更新起点到点v的最短路径值
q.push(dis[v]);//入队
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&g);//输入,根据题目来
for(int a,b,c,i=1;i<=m;++i)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);//加边
add(b,a,c);//加边,如果是有向图,忽略这一步操作
}
dij();//调用函数
if(dis[n].w>=0x3f3f3f-1) printf("-1");
//这里是输出操作,如果起点到点n的值大于0x3f3f3f-1,就说明压根就没更新到,也说明起点和点n不连接
else printf("%d",dis[n].w);
return 0;
}
void add(int u,int v,int w)//加边操作
{
e[++cnt].v=v;//记录该条边的目标点
e[cnt].w=w;//记录边权
e[cnt].nxt=h[u];//记录上一条边
h[u]=cnt;//更新从点u发出的最后一条边的边号
}

dijkstra最短路算法(堆优化)的更多相关文章

  1. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  2. Dijkstra最短路算法

    Dijkstra最短路算法 --转自啊哈磊[坐在马桶上看算法]算法7:Dijkstra最短路算法 上节我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最 ...

  3. 【坐在马桶上看算法】算法7:Dijkstra最短路算法

           上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短路”.本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径 ...

  4. 最短路-朴素版Dijkstra算法&堆优化版的Dijkstra

    朴素版Dijkstra 目标 找到从一个点到其他点的最短距离 思路 ①初始化距离dist数组,将起点dist距离设为0,其他点的距离设为无穷(就是很大的值) ②for循环遍历n次,每层循环里找出不在S ...

  5. 最短路模板|堆优化Dijkstra,SPFA,floyd

    Ⅰ:Dijkstra单源点最短路 1.1Dijkstra const int MAX_N = 10000; const int MAX_M = 100000; const int inf = 0x3f ...

  6. Dijkstra算法堆优化详解

    DIJ算法的堆优化 DIJ算法的时间复杂度是\(O(n^2)\)的,在一些题目中,这个复杂度显然不满足要求.所以我们需要继续探讨DIJ算法的优化方式. 堆优化的原理 堆优化,顾名思义,就是用堆进行优化 ...

  7. BZOJ 3040 最短路 (堆优化dijkstra)

    这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...

  8. NEU 1664 传送(最短路基础 堆优化Dijkstra)

    题目描述 小A最近喜欢上一款游戏:游戏把地图分了一些区域,这些区域可能会重叠,也可能不会. 游戏中有一项传送技能,改传送技能只能将在同一区域的两个地方使用.小A可以利用区域中重叠部分来实现从某一区域到 ...

  9. Dijkstra算法堆优化

    转自 https://blog.csdn.net/qq_41754350/article/details/83210517 再求单源最短路径时,算法有优劣之分,个人认为在时间方面 朴素dijkstra ...

随机推荐

  1. Redis源码漂流记(二)-搭建Redis调试环境

    Redis源码漂流记(二)-搭建Redis调试环境 一.目标 搭建Redis调试环境 简要理解Redis命令运转流程 二.前提 1.有一些c知识简单基础(变量命名.常用数据类型.指针等) 可以参考这篇 ...

  2. vue - Vue脚手架(终结篇)/ vue动画

    几天的内容不是很多,因为我们脚手架的学习告一段落了,也是为了跟明天开始的内容有一个区分. 明天将会有一个非常重要的内容来了,各位,vue中的ajax他来了,这个绝对是重量级,有点兴奋! 十一.TODO ...

  3. linux项目部署(非前后端分离crm)

    参考博客 参考博客2---部署过程 导论:看参考博客1 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收 ...

  4. .NET混合开发解决方案13 自定义WebView2中的上下文菜单

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  5. RocketMq 完整部署

    目录 RocketMq 部署 环境 物理机部署 自定义日志目录 自定义参数和数据存放位置 服务启动 启动name server 启动broker 关停服务 尝试发送消息 常见报错 部署 rockerm ...

  6. Install Ubuntu on Windows Subsystem for Linux

    安装参考 ubuntu.com/wsl microsoft/wsl/install-manual microsoft/terminal 错误解决方案 github/启动 WSL 2时警告"参 ...

  7. ArcGIS和ArcEngine导出地图时,png格式支持背景透明

    1.ArcGIS支持导出PNG,背景透明 导出png时,背景色和透明色不能设置为空,必须设置为同一个颜色,通常使用白色. 2.ArcEngine支持导出PNG,背景透明 //1.创建export IE ...

  8. 技术分享 | 云原生多模型 NoSQL 概述

    作者 朱建平,TEG/云架构平台部/块与表格存储中心副总监.08年加入腾讯后,承担过对象存储.键值存储,先后负责过KV存储-TSSD.对象存储-TFS等多个存储平台. NoSQL 技术和行业背景 No ...

  9. Proxmox 7.2 部署 DoraCloud桌面云,支持vGPU

    介绍 本文介绍了使用Proxmox + DoraCloud,将一台图形工作站(配置有Tesla P4显卡)改造成一台桌面云主机.可以满足多个桌面用户同时使用3D应用的需求. 该方案适合于小型工作室.电 ...

  10. Abp Vnext源码解析系列文章01---EventBus

    一.简介 BP vNext 封装了两种事件总线结构,第一种是 ABP vNext 自己实现的本地事件总线,这种事件总线无法跨项目发布和订阅.第二种则是分布式事件总线,ABP vNext 自己封装了一个 ...