1.有向无环图的单源点最短路
其实跟之前说的最长路是一样的
思路:广搜(拓扑排序)+ DP
如下图所示:

2.一般图的单源点最短路
Dijkstra(迪杰斯特拉)算法
算法思路:每次找离起点最近的那个点,确认它的最短路径值(这个点的最短路必须已经确认了),拿这个点去更新与它相邻的点,不断重复这个操作,从离起点的距离一点一点扩展开,有种贪心+bfs的感觉
举个栗子

说说用Dijkstra求最短路的过程
一开始将所有点到原点的距离设置为正无穷,从1号点出发,更新2号,4号,6号点到原点的距离,dis[2]=2,dis[4]=1,dis[6]=3,4号是到1号最近的点,4号去更新2号的值,更新不了,11>2,然后4号更新7号的值,dis[7]=3,此时2离起点最近,2号能更新到的点是3号和5号,此时需要考虑的是dis[6]=3,dis[7]=3,di[5]=7,dis[3]=8,6号离起点最近,然后7号也离起点最近,再用7号点去更新与它相邻的点5号和8号,dis[5]=6,dis[8]=11,5号离原点最近,用5号更新3号和8号的值,3号更新不了,11>8,更新8号dis[8]=6+4=10,得到最短路的数值10
适用于有向图和无向图,也可带环,不适用于有负权边的图

算法重复从结点集合v-s中选择最短路径最小的点结点u加入到集合s,然后对u的出边进行松弛操作,当把一个结点选进集合s后,就意味着已经找到了从源点到这个点的最短路径,但若存在负权边,就与这个前提矛盾,可能会出现的出的距离加上负权后比已经的到的最短路径还短的情况
比如说这个图,用Dijkstra它会认为1到2的最短路径是3,但其实是2,因为bfs最大的特点就是短视,它只能看到与自己相邻的点的情况,对于远方,它就懵了,如果有一边负的,它不知道多走一边会减小它的值
代码实现:

#include<bits/stdc++.h>//O(n方)
using namespace std;
int mp[100][100];
int inf = 99999999;
int dis[100];
int book[100]={0};
int main() {int n, m;cin >> n >> m; //顶点数,边数int a, b, c;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (i == j)mp[i][j] = 0;elsemp[i][j] = inf; //初始化}}for (int i = 1; i <= m; i++) {cin >> a >> b >> c;mp[a][b] = c; //建图}for (int i = 1; i <= n; i++) {dis[i] = mp[1][i];}book[1] = 1;//Dijkstra算法的核心部分int u;for (int i = 1; i <= n - 1; i++) {//找离原点最近的点 int minn = inf;for (int j = 1; j <= n; j++) {if ( book[j] == 0&&dis[j] < minn ) {minn = dis[j];u = j;}}book[u] = 1;for (int v = 1; v <= n; v++) {if (mp[u][v] < inf) {if (dis[v] > dis[u] + mp[u][v])dis[v] = dis[u] + mp[u][v];}}}cout<<dis[n]<<endl;
}

这种朴素算法的时间复杂度是n的平方,而一般题目给的数据都是差不多le5,这时候肯定会爆,
所以我们用堆优化来降低时间复杂度
时间复杂度降到nlogn+m
堆优化了每次找离起点最近的点的时间复杂度。
邻接表优化了对于每一个基点,更新它的所有邻边的时间复杂度(上面那个就是1扫到n,很花时间)
链式前向星+优先队列

priority_queue默认的是大根堆
priority_queue支持小根堆的一种方法

priority_queue<int,vector<int>,greater<int>> q;

可以看到,我们把距离放在pair对的第一个,把对应的点放在pair对的第二个,这是因为小根堆的比较对象是pair对的第一个元素
而我们正是要对距离排序,把离起点最近的距离放在堆顶
算法思路:
1.链式前向星存边
2.采用优先队列和c++中的二元组pair,它相当于一个包含两个变量的结构体,所以这里也可以用结构体实现,使用重载运算符(结构体的内嵌比较函数),但是我不太会,所以就没用
3.每次离原点最近的点都放在堆顶,并且用vis数组记录访问过的点,防止来回兜圈
4.弹出堆顶,搜索堆顶的所有连边,如果从起点到v的距离大于从从起点到u的距离+从u到v的距离,那么就更新最小距离,把它对应的点和距离加入队列
5.遍历,输出值即可
代码实现:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 2e5;
struct node
{int v,next,w;
}edge[maxn];
int cnt;
bool vis[maxn];
int dis[maxn],head[maxn];
void add(int u,int v,int w)//起点,终点,距离,链式前向星建图
{edge[cnt].w=w;edge[cnt].v=v;edge[cnt].next=head[u];head[u]=cnt++;
}
void dijkstra(int n)
{priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;memset(dis,inf,sizeof dis);q.push({0,1});dis[1]=0;while(!q.empty()){pair<int,int> temp = q.top();//记录堆顶,即堆内最小的边并将其弹出 q.pop();int u = temp.second;//点 if(vis[u]) continue;//如果被访问过,就跳过 vis[u]=true;//标记 for(int i = head[u];i!=-1;i=edge[i].next)//搜索堆顶的所有连边 {int v = edge[i].v;if(dis[v]>dis[u]+edge[i].w)//松弛操作 {dis[v]=dis[u]+edge[i].w;q.push({dis[v],v});//把新遍历的点加到堆中 }}}//if(dis[n]==inf) cout<<-1<<endl;//else cout<<dis[n]<<endl;for(int i=1;i<=n;i++)cout<<dis[i]<<endl;
}
int main()
{int n,m,u,v,w;cin>>n>>m;memset(head,-1,sizeof(head));for(int i = 0;i<m;i++){cin>>u>>v>>w;add(u,v,w);}dijkstra(n);return 0;
}
/*  测试数据 6 91 2 11 3 122 3 92 4 33 5 54 3 44 5 134 6 155 6 4*/

Dijkstra算法及堆优化相关推荐

  1. dijkstra算法及其堆优化

    dijkstra算法及其堆优化 (个人笔记写给自己看的) 数据结构:链式前向星,优先队列 dijkstra算法: vis数组初始化为0,dis数组初始化为inf(很大的值如:0x7fffffff),设 ...

  2. Dijkstra算法和堆优化

    目录 Dijkstra介绍 算法思想 具体步骤 代码实现 Dijkstra链式向前星 优化思路 实现步骤 代码实现 Dijkstra链式向前星堆优化 优化思路 优化步骤 代码实现 参考资料(帮助理解代 ...

  3. Dijkstra算法(堆优化版求稀疏图最短路)

    南昌理工acm集训队 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959年提出的,是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题. 基本思想 Dijkstra算法是用来解决不 ...

  4. DijKstra算法普通+堆优化链式向前星

    朴素版本 #include<bits/stdc++.h> using namespace std; const int maxn = 10010; const int inf = 0x3f ...

  5. 最小生成树 Kruskal 和 Prim算法及堆优化

    目录 生成树/最小生成树是什么. 一.Kruskal算法 Kruskal模板 二.Prim算法及堆优化 1.遍历 Prim 普通模板 2.堆优化 Prim 堆优化模板 解决最小生成树的问题之前,我们先 ...

  6. 迪杰斯特拉算法及其堆优化

    迪杰斯特拉算法及其堆优化 迪杰斯特拉算法是一种求解图的单点最短路径的算法. 一句话来说就是找最近点,更新相邻距离,再找最近点,更新相邻距离 迪杰斯特拉算法的原理是 1.首先在没有中间节点的情况下,也就 ...

  7. 【Dijkstra算法】未优化版+优先队列优化版

    https://blog.csdn.net/YF_Li123/article/details/74090301 Dijkstra算法伪代码://G为图:数组d为源点到达各点的最短路径长度,s为起点 D ...

  8. 第六天PAT-A1003 Emergency最短路问题Dijkstra算法(小根堆)描述及模板

    A1003 Description: 作为一个城市的急救队领导,你会得到你所在城市的一个特别地图.这张地图展示了一些由一些路径相连的几个零散的城市.每个城市的救援队总数和连接两个城市的道路的长度都标注 ...

  9. 朴素版Dijkstra算法

    文章目录 一.Dijkstra是什么? 二.使用步骤 1.Dijkstra的基本原理 2.时间复杂度 三.代码实现思路 四.代码实现 总结 一.Dijkstra是什么? Dijkstra算法是由荷兰计 ...

最新文章

  1. 最大流 ---- 最小路径覆盖 ---- P2765魔术球问题(网络流24题)
  2. [Swift]在不依赖三方库的情况下如何异步下载和缓存图片?
  3. Tachyon 0.7.1伪分布式集群安装与测试
  4. Java中对象的深克隆和浅克隆
  5. python如何加密字符串_Python实现对字符串的加密解密方法示例
  6. 在Visual Studio Code运行单个js文件需要用到插件
  7. ubuntu 安装php 5.4.9 编译安装
  8. 署名用by还是from_介词专题|工作“到7点”是By 7pm还是Until 7pm?
  9. JAVA基础,输入/输出(I/O)流
  10. Ant design
  11. 个人理财管理系统代码
  12. Android Studio Logcat 截断问题(cocos2d-x 篇)
  13. SpringBoot Mybatis 读写分离配置
  14. Python:实现graham scan葛立恒扫描法算法(附完整源码)
  15. 安全总结(一)--一键彻底关闭Win10自带Windows Defender杀毒软件
  16. Linux调试排错命令
  17. SqlDBHelper(基础增删改查)
  18. [CF1153F]Serval and Bonus Problem(dp/积分+OGF)
  19. MyEclipse 快捷键大全(@Hcy)
  20. remote desktop mac(微软远程连接工具)

热门文章

  1. 王者荣耀体验服服务器未响应9月16,王者荣耀体验服9月16日更新公告 西施二技能增强...
  2. MySQL 安装失败,提示Apply Security Settings 的处理办法
  3. Factorio Headless 服务器搭建教程
  4. MINA研究-源代码
  5. 十年创业老兵谈人才招聘:瘦鹅理论
  6. 学习使用SwiftUI开发MacOS应用 - 第1节 如何创建SwiftUI 应用并实现窗口交互
  7. 电子信息专硕何去何从?很多大学都能调整为计算机专硕!
  8. 中国互联网十年白皮书
  9. CCC安规之跌落测试
  10. 模拟Vue响应式原理