迪杰斯特拉 + 链式前向星 + 优先队列

2023-10-20 03:08

本文主要是介绍迪杰斯特拉 + 链式前向星 + 优先队列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

链式前向星

邻接矩阵存图对于稀疏图(边少)会有很大的空间浪费,这时候防止卡内存,可以用邻接表来存图,但邻接表使用涉及指针,难度较大,可以用数组模拟指针,也就是前向星,但前向星要排序,至少nlogn,而链式前向星可以避免排序操作,降低时间复杂度

前向星博文推荐

作者:sugarbliss
来源:CSDN

链式前向星使用要点

①edge[i].next存同起点的边的上一个点
②head[u]存以u为起点的最后一条输入的边
③head[u] 如果初始化为 -1 那么判断是否还有同起点的边就判断 要edge[i].next 是否 = -1,
④快速判断 i == -1 可以用 ~i
⑤对于无向图 输入的边要 以两个顶点各自为起点都存一边 所以edge[]数组大大小 要申请两倍以上的边的数量

dijstra算法原理

作用:求解单源点无负权边最短路问题

初始时,所有以源点为起点的边中 边权最小的边的终点和源点的距离一定已经是最短了(不用再优化,可以确定下来),因为别的边到源点的边都比这条边的边权长,又没有负边,所以无法对这个最短边的终点进行优化。(所以也很明显这个思想不能用来求最长路,因为初始时与源点最长的边,后面可以被其它边优化的更长。)

基于这一个特点每次都可以选出一个到源点最近的点来优化其它点到源点的距离,优化后这个用来优化其他点距离的点就可以丢掉不管了(因为这个点的边已经尽可能的被优化到最短了),得再选一个到源点最近的点,重复以上过程就可以了完成对所有点的单短路求解。

结合优先队列

上述对最短边的筛选可以用优先队列(最小堆),当然要自己写个排序规则
eg

struct point{   //链式前向星模拟邻接表int to;     //作为链式前向星时当做终点,用来堆排序时当做起点入堆int w;      //权重int next;   //上个同起的边的位置bool operator  < (const point &b) const //堆排序规则要反过来{return w > b.w;}
};

存边用链式前向星



例题 公交线路

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1000000;
const int N = 1000000;struct point{   //链式前向星模拟邻接表int to;     //终点int w;      //权重int next;   //上个同起的边的位置bool operator  < (const point &b) const //堆排序规则{return w > b.w;}
};priority_queue<point> q;
point edge[MAX];//存边
int head[N];
bool vis[N];//判断这个点是否已经确定
int dist[N];//起点到这个点的距离int cnt = 0;void addedage(int x,int y,int z){edge[cnt].to = y;edge[cnt].w = z;edge[cnt].next = head[x];head[x] = cnt++;
}bool dijstra(int s,int t){        //s是起点坐标 t是要查寻得点得坐标point t1,t2;t1.to = s;              //当起点来用t1.w = 0;dist[s] = 0;q.push(t1);while(!q.empty()){t1 = q.top(); q.pop();if(vis[t1.to])  continue;//一个点可能被多次优化 所以会多次进队列//但这个点在堆顶一定是最小的,边就是这个点到起点的最短距离//如果已经确定他的最短距离,就说明已经拿来优化过别的点  vis[t1.to] = true;      //表示点已经确定for(int i = head[t1.to];~i;i = edge[i].next){//遍历以t1.to为起点的所有可以优化的终点int u = edge[i].to;//要优化的终点if(!vis[u] && dist[u] > dist[t1.to] + edge[i].w){dist[u] = dist[t1.to] + edge[i].w;t2.to = u;t2.w = dist[u];q.push(t2); }}}if(dist[t] >= 0x3f3f3f3f)return false;return true;
}int main(){int x,y,z;//点1 点2 权值int n,m,s,t;cin >> n >> m >> s >> t;memset(head,-1,sizeof(head));//第一个点没有上一个点memset(dist,127,sizeof(dist));//8位最大值 2^7 - 1for(int i = 0;i < m;i++){   cin >> x >> y >> z;addedage(x,y,z);addedage(y,x,z);//无向图}if(dijstra(s,t))cout << dist[t] << endl;else cout << -1 << endl;//system("pause");return 0;
}

为什么不适用于负边的的例子
在这里插入图片描述

起点s,终点t,用dijstra算法可以确定A的最短路是1,但实际上可以用-10的边优化,A实际的最短路是-5,所以有负权边的图不能用dijkstra跑。

这篇关于迪杰斯特拉 + 链式前向星 + 优先队列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/244191

相关文章

hdu1180(广搜+优先队列)

此题要求最少到达目标点T的最短时间,所以我选择了广度优先搜索,并且要用到优先队列。 另外此题注意点较多,比如说可以在某个点停留,我wa了好多两次,就是因为忽略了这一点,然后参考了大神的思想,然后经过反复修改才AC的 这是我的代码 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 2431 poj 3253 优先队列的运用

poj 2431: 题意: 一条路起点为0, 终点为l。 卡车初始时在0点,并且有p升油,假设油箱无限大。 给n个加油站,每个加油站距离终点 l 距离为 x[i],可以加的油量为fuel[i]。 问最少加几次油可以到达终点,若不能到达,输出-1。 解析: 《挑战程序设计竞赛》: “在卡车开往终点的途中,只有在加油站才可以加油。但是,如果认为“在到达加油站i时,就获得了一

poj3750约瑟夫环,循环队列

Description 有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。 Input 第一行输入小孩的人数N(N<=64) 接下来每行输入一个小孩的名字(人名不超过15个字符) 最后一行输入W,S (W < N),用

POJ2010 贪心优先队列

c头牛,需要选n头(奇数);学校总共有f的资金, 每头牛分数score和学费cost,问合法招生方案中,中间分数(即排名第(n+1)/2)最高的是多少。 n头牛按照先score后cost从小到大排序; 枚举中间score的牛,  预处理左边与右边的最小花费和。 预处理直接优先队列贪心 public class Main {public static voi

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空

深度优先(DFS)和广度优先(BFS)——算法

深度优先 深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支,当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei

多线程篇(阻塞队列- LinkedBlockingDeque)(持续更新迭代)

目录 一、LinkedBlockingDeque是什么 二、核心属性详解 三、核心方法详解 addFirst(E e) offerFirst(E e) putFirst(E e) removeFirst() pollFirst() takeFirst() 其他 四、总结 一、LinkedBlockingDeque是什么 首先queue是一种数据结构,一个集合中

Java消息队列:RabbitMQ与Kafka的集成与应用

Java消息队列:RabbitMQ与Kafka的集成与应用 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在现代的分布式系统中,消息队列是实现系统间通信、解耦和提高可扩展性的重要组件。RabbitMQ和Kafka是两个广泛使用的消息队列系统,它们各有特点和优势。本文将介绍如何在Java应用中集成RabbitMQ和Kafka,并展示它们的应用场景。 消息队