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

迪杰斯特拉算法是一种求解图的单点最短路径的算法。
一句话来说就是找最近点,更新相邻距离,再找最近点,更新相邻距离
迪杰斯特拉算法的原理是
1.首先在没有中间节点的情况下,也就是直达路径中找到到达某点p的最短路径。易知,该路径一定是原点到点p的最短路径。将点p标记在vis数组中,并将最短路径的值存在dist数组中。
2.再对所有节点进行松弛操作,也就是下一个节点的最短路径有两种情况,一种是经过某个已知的最短路(就是被vis标记的最短路径),第二种情况是直达。所以,求解下一个最短路径就是求解递推公式
dist[i]=min(dist[i] , map[i][now]+dist[now])
now是上一个最短路径。
3.找到最短的dist并标记在vis中,并迭代2,3步。
总体来说,迪杰斯特拉算法是按从小到大的顺序求解到各个点的最短路径,每求出一个最短路径,下次循环时就判断所有的点(其实等同于没有求出最短路径的点)如果经过上一个已经求出最短路径的点,是否会出现更短的路径(这一步就成为松弛操作)。在遍历所有点的同时,找到没有求出最短路径的点中的最短路径,并保存。
没有优化的迪杰斯特拉算法的时间复杂度为O(n*n)。
下面是一张图解:

以下是参考代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x7fffffff
long long int dist[100100];
int Map[1000][1000];
int vis[1010];
int main(){int n,m,s;while(~scanf("%d%d%d",&n,&m,&s)){for( int i=1;i<=n;i++){for( int j=1;j<=n;j++){Map[i][j]=0x7fffffff;}dist[i]=0x7fffffff;}memset(vis,0,sizeof(vis));for( int i=1;i<=m;i++){int from,to,val;cin>>from>>to>>val;Map[from][to]=min(val,Map[from][to]);Map[to][from]=min(val,Map[from][to]);   }dist[s]=0;vis[s]=1;int start=s;for( int j=1;j<=n;j++){int next, minn=0x7fffffff;;for( int i=1;i<=n;i++){if(Map[start][i]!=inf) {dist[i]=min(dist[i],Map[start][i]+dist[start]);}if(vis[i]==0&&dist[i]<minn){next=i;minn=dist[i];}  }if(minn==inf)break;start=next;vis[start]=0;}for( int i=1;i<=n;i++){cout<<dist[i];if(i!=n) cout<<" ";}cout<<endl;}
}

对迪杰斯特拉算法的优化:
上面的迪杰斯特拉算法主要缺陷是,每当找到一个最短路径,如果需要找下一个最短路径,就需要在完成松弛操作之后,遍历dist数组,寻找其中的最小值。遍历dist数组的时间复杂度为O(n)。
如果图的边数为n*(n-1),那么每找到一个最小值,所要进行的松弛操作数就是n-1,这和遍历dist数组可以同时进行,算法优化的空间不大。
然而,如果是稀疏图,每找到一个最小值,所要进行的松弛操作数就远小于n-1,这时就可以对算法进行优化。优化的关键是省去对dist的线性查找,如果每次可以直接返回dist中的最大值,就可以大大减小算法的时间复杂度。
堆优化后的迪杰斯特拉算法复杂度为ElogE

#include<bits/stdc++.h>
using namespace std;
#define inf 0x7fffffff
struct p{long long int to,val,next;
};
p edge[200100];
long long int dist[100100];
int vis[100100];
int head[100100];
int cnt;
void add_edge( long long from,long long to,long long  val){edge[++cnt].val=val;edge[cnt].to=to;edge[cnt].next=head[from];head[from]=cnt;
}
struct node{long long int from,val;bool operator <(const node &a ) const{return a.val<val;}
};
int main(){int n,m,s;while(~scanf("%d%d%d",&n,&m,&s)){cnt=0;memset(edge,0,sizeof(edge));for( int i=1;i<=n;i++){dist[i]=1e12;head[i]=0;vis[i]=0;}for( int i=1;i<=m;i++) edge[i].val=1e12;for( int i=1;i<=m;i++){long long int from,to,val;scanf("%lld%lld%lld",&from,&to,&val);add_edge(from,to,val);}dist[s]=0;priority_queue<node>q;q.push({s,0});while(!q.empty()){node now=q.top();q.pop();if(vis[now.from]) continue;vis[now.from]=1;for( long long int  i=head[now.from];i!=0;i=edge[i].next){int j=edge[i].to;if(dist[now.from]+edge[i].val<dist[j]){//进行松弛操作dist[j]=dist[now.from]+edge[i].val;q.push({j,dist[j]});}}}for( int i=1;i<=n;i++){printf("%lld ",dist[i]);}cout<<endl;    }
}

迪杰斯特拉算法的优化可以总结为以下几步:
1.将最短距离出队。
2.进行松弛操作,并将成功松弛的点入队。

迪杰斯特拉算法及其堆优化相关推荐

  1. dij算法堆优化_迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少

    算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即:U ={其余顶点},若v与U中顶点u有边,则(u,v)为正常权值,若u不是v的出边邻接点,则(u, ...

  2. dij算法堆优化_迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少(示例代码)...

    算法实现步骤: a.初始时,只包括源点,即S = {v},v的距离为0.U包含除v以外的其他顶点,即:U ={其余顶点},若v与U中顶点u有边,则(u,v)为正常权值,若u不是v的出边邻接点,则(u, ...

  3. 堆优化版迪杰斯特拉算法

    先是朴素版的迪杰斯特拉算法 存储结构为邻接矩阵 int dijstra(int n) {for (int i = 1; i <= n; i++){dist[1] = 0;int index = ...

  4. 迪杰斯特拉算法优化(dijkstra)

    dijkstra常规实现方式:迪杰斯特拉算法(dijkstra)https://blog.csdn.net/weixin_48898946/article/details/120990493 这里主要 ...

  5. 迪杰斯特拉算法 两点间最短路径的选择

    百度首页 登录 注册 新闻网页贴吧知道音乐图片视频地图百科文库 首页 分类 艺术 科学 自然 文化 地理 生活 社会 人物 经济 体育 历史 特色百科 历史上的今天 数字博物馆 史记·2015 城市百 ...

  6. c++ 遍历所有点且距离最短_图解:最短路径之迪杰斯特拉算法

    小禹禹们,你们好,景禹最近已经开学,忙着准备毕业答辩的事情,这才抽身个大家更新文章,还请莫怪.生活实属不易,有时候让人有点儿焦头烂额,甚至想让景禹放弃继续更新文章,可是千百号人默默地关注者景禹,当然也 ...

  7. 图论的灵魂——带你走进迪杰斯特拉算法的世界

    你好,我是小黄,一名独角兽企业的Java开发工程师. 感谢茫茫人海中我们能够相遇, 俗话说:当你的才华和能力,不足以支撑你的梦想的时候,请静下心来学习 希望优秀的你可以和我一起学习,一起努力,实现属于 ...

  8. 643-Dijkstra迪杰斯特拉算法

    Dijkstra迪杰斯特拉算法 每个顶点之间的边都带着1个权值,这个权值可以表示任意的花费,距离,时间等等. 比如说我们指定一个起始的顶点A,和一个末尾的顶点E, 如果我们要求这2个单元之间的最短路径 ...

  9. java迪杰斯特拉算法介绍_178-迪杰斯特拉(Dijkstra)算法基本介绍

    2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2) ...

最新文章

  1. TensorFlow六种激活函数
  2. 重磅直播|中科慧眼崔峰博士详解深度相机原理及其应用
  3. java org.jb2011报错_Java中getResourceAsStream()用法总结(转)
  4. 【Git 】命令总结记录
  5. [leetcode-515-Find Largest Value in Each Tree Row]
  6. 漫画 | 程序员离职事件始末
  7. 自我总结 (三) --(Java Web学习)
  8. c语言在一个文件后面添加数据类型,c语言简单入门之简单运行和数据类型
  9. [渝粤教育] 三江学院 大学生创新基础课程 参考 资料
  10. 最近,程序员又被区别对待了
  11. HDFS常用文件操作命令汇总
  12. 使用IntelliJ IDEA 构建Maven的web项目
  13. SQL 中having 和where的区别(转)
  14. 全连接的多层神经网络结构(MultiLayerNet)
  15. 最大权闭合子图(poj 2987 Firing)
  16. oc基础-protocol协议的使用
  17. 拓端tecdat|R语言动态可视化:制作历史全球平均温度的累积动态折线图动画gif视频图
  18. 异步 Action 的定义
  19. 新手学编程必会的100个代码
  20. ORL Face94 LFW

热门文章

  1. linux中mpich的运行线程,Linux下MPICH的安装与使用
  2. 昆山第二中等专业学校计算机分数线,江苏昆山第一中等专业学校2021年招生录取分数线...
  3. 高质量音频转换器,如何转换成mp3音频格式
  4. 怎么把几个gif图片合成一个gif?一键gif合成的方法
  5. 从制造到“智”造,工业数据分析的转身与蜕变
  6. 正则表达式解英语单词字谜
  7. [激光原理与应用-56]:激光器 - 电路 - PID温度控制算法的参数调整
  8. 接入B站iframe视频(bilibili引用视频)
  9. 新版 MSN.com 网站
  10. Android小项目——简易备忘录