首页 > 编程语言 >Dijkstra单源最短路堆优化算法

Dijkstra单源最短路堆优化算法

时间:2024-12-23 13:42:27浏览次数:3  
标签:node 优先 优先级 队列 短路 单源 priority Dijkstra cmp

Dijkstra单源最短路堆优化算法

使用基于堆的优先队列,我们可以在进行松弛操作前对找边进行优化操作

时间复杂度为 \(O(m\log m)\) ,其中 \(m\) 为边的数量,优先队列找边的时间复杂度为\(O(\log m)\)

优先队列

默认为一个大根堆,即堆顶的元素的优先级最高,体现在某个变量的值

每次从队列中取出堆顶元素,我们依据堆的特性,可以选出当前最优的节点,再对这个节点进行访问,对其可联通点进行一轮松弛操作,最后将这些点依次压入队列中,优先队列会帮助我们将这些点进行优先级排序

对于Dijkstra而言,我们将节点放入优先队列中,我们的边权w作为的是优先级评判变量,但是,我们最优考虑的点为边权最小的点,所以这就有两种办法来解决这个问题

  • 将边权取负后放入队列
  • 使用重载运算符,实现小根堆的优先队列

介绍第一种操作:

边权作为优先队列的优先级依据,它的值越大优先级越高,我们需要值越小(当前最优)的边优先级最高,所以可以先对边权取负再放入队列中

priority_queue<pair<int, int>> q;//二元组队列,存储边权和联通点
void dijkstra(int s) {
	presetdis();//预处理距离
	q.push({ 0,s });//起始点到自己的距离为0,压入队列
	dis[s] = 0;
	while (q.size())//当队列不空时
	{
		auto t = q.top();//取出堆顶元素
		q.pop();//弹出堆顶元素
		if (vis[t.second]) continue;//如果堆顶元素这个节点已被访问过,重新取元素
		vis[t.second] = 1;//标记这个节点已被访问
		for (auto it = e[t.second].begin(); it != e[t.second].end(); it++) {//迭代访问
			dis[it->v] = min(dis[t.second] + it->w, dis[it->v]);//松弛操作
			q.push({-(dis[it->v]),it->v});//压入更新后的节点
		}
	}
}

其中,first存储边权,second记录联通点,优先队列默认以pairfirst作为优先级标准

q.push({-(dis[it->v]),it->v})对权值取负,即依靠大根堆直接排序


重载运算符的操作

先来看一下priority_queue的原型声明

其中的 Type为数据类型,Container为容器(vector,deque...),Functional为比较方式

priority_queue<Type, Container, Functional>

对于一般的独立变量而言,构造小根堆只需要在默认的大根堆写法上稍加修改

priority<int> q;//大根堆
priority<int, vector<int>, greater<int> > q;//小根堆

处理结构体变量时,需要更复杂的操作,使优先队列依照结构体内的某个成员进行优先级排序

这里使用的是定义 cmp 函数,重载运算符来进行小根堆的实现

struct node{
    int x;
    int y;
};
struct cmp{
    bool operator()(node a,node b){
        return a.x > b.x;
    }
};
priority_queue<node,vector<node>,cmp> q;

struct cmp 定义了一个自定义的比较器,operator() 是一个重载运算符,允许 cmp 作为函数对象使用

接收两个 node 对象 ab,如果 a.x 大于 b.x 就返回 true ,优先队列将根据 x 的值进行排序,较小的 x 值优先

注意,这里的 cmp 函数逻辑和 sort 中的 cmp 的逻辑相反

bool compare(node a, node b) {
    return a.x > b.x; // 降序排序,大的值在前
}
//当 a.x 大于 b.x 时,返回 true,表示在优先队列中,a 不是优先于 b 的

bool operator()(node a, node b) {
    return a.x > b.x;// 小根堆,大的值优先级更低
}
当 a.x 小于 b.x 时,返回 true,表示 a 在 b 之前

也可以将重载运算符的操作放在结构体内

struct node{
    int x;
    int y;
    bool operator<(const node &a) const
    {
        return x>a.x;
    }
};
priority_queue<node> q;

nodex 值被用来进行比较,这里是 x > a.x,表示当 x 值较大时会被认为是“优先级较小”

优先队列在处理 node 时,将会以 x 值从大到小的顺序排列

标签:node,优先,优先级,队列,短路,单源,priority,Dijkstra,cmp
From: https://www.cnblogs.com/dianman/p/18623784

相关文章

  • 最短路相关技术
    板子是一定要记的,但不够,全是思维题,要解放思想开动脑筋。板子Floyd是全源最短路。只要最短路存在(无负环),不管有向无向,边权正负,都可以用。板子for(intk=1;k<=n;++k){for(inti=1;i<=n;++i){for(intj=1;j<=n;++j)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]......
  • 揭示Newman教授的错误:Dijkstra算法的松弛次序与最短路径中的边次序不一定相同
    揭示Newman教授的错误:Dijkstra算法的松弛次序与最短路径中的边次序不一定相同Dijkstra算法简介Newman教授的观点反驳观点示例图Dijkstra算法的执行过程分析松弛次序与最短路径中的边次序结论C语言实现Dijkstra算法在探讨Dijkstra算法的松弛次序是否一定与最......
  • 数据结构与算法学习笔记----Dijkstra
    数据结构与算法学习笔记----Dijkstra@@author:明月清了个风@@firstpublishtime:2024.12.17ps⭐️两个版本的都是模版题,算法讲解直接放在每一题里了,思路中还有对于稀疏图和稠密图的介绍,注意优化版的dijkstra中有几点注意点是和朴素版不一样的。Acwing849.Dijkstr......
  • Dijkstra单源最短路朴素算法(空间优化)
    Dijkstra单源最短路朴素算法(空间优化)基于使用邻接表存储连接边的方法,可以有效的降低空间复杂度在稀疏图(边的数量远小于顶点数量平方的图)中,邻接矩阵会大量占用无用的内存,导致Re,我们采用邻接表的办法,只存储存在的边,减少无关占用。相反,在稠密图(边的数量接近顶点数的平方的图)中,邻接......
  • 【MATLAB源码-第247期】基于matlab的秃鹰搜索优化算法(BES)无人机三维路径规划,输出做
    操作环境:MATLAB2022a1、算法描述秃鹰搜索优化算法(BaldEagleSearch,BES)是一种新颖的群体智能优化算法,受自然界中秃鹰猎食行为的启发而设计。与其他群体智能算法类似,BES试图通过模拟自然界的某些行为来解决复杂的优化问题。该算法的核心思想是通过模拟秃鹰在猎食过程中的......
  • 多源最短路Floyd算法
    多源最短路算法-Floyd使用Floyd(弗洛伊德)算法,可以以\(O(n^3)\)的时间复杂度求出一张多源图的任意两点间的最短路径一般采用邻接矩阵的方法来存储图:intg[N][N];g[i][j]其中,g[i][j]的意义为第i个节点到第j个节点的权重我们需要对邻接矩阵进行路径初始化,将自身到自身的权重......
  • PbootCMS如何启用文章短路径模式?
    PbootCMS支持文章短路径模式,这种模式允许文章访问地址不再携带栏目地址,而是直接挂在根路径。启用文章短路径模式可以使文章URL更加简洁,提升用户体验。以下是详细的启用步骤和注意事项:启用文章短路径模式进入PbootCMS后台管理系统。导航到“全局配置”模块。选择“URL规则”......
  • 最短路----Dijkstra算法详解
    简介迪杰斯特拉(Dijkstra)算法是一种用于在加权图中找到单个源点到所有其他顶点的最短路径的算法。它是由荷兰计算机科学家艾兹格·迪科斯彻(EdsgerDijkstra)在1956年提出的。Dijkstra算法适用于处理带有非负权重的图。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法,每次遍历......
  • 同余最短路
    同余最短路同余最短路可以用于解决形如"给定\(n\)个整数,求这\(n\)个整数能拼凑出多少的其他的整数(\(n\)个整数可以重复选取)"以及"给定\(n\)个整数,求这\(n\)个整数不能拼凑出的最小(最大)的整数",或者"至少要拼几次才能拼出模\(k\)余\(p\)的数的问题......
  • Dijkstra 最短路径算法
    此篇文章在2023年9月28日被记录Dijkstra算法的核心点是贪心算法:不断寻找最短的点,在最短的点上更新最短路径1.前言想要了解学习Dijkstra算法,需要先了解无向图与权重图,无向图顾名思义就是没有方向的图,下面表示了有向图和无向图以及权重图2.什么是Dijkstra算法Dijkstra算法......