迪杰斯特拉(Dijkstra) —— 最短路算法
Dijkstra是最短路基础算法之一(还有判负环的SPFA和多源最短路的Floyd),但在正常情况下Dijkstra是最快的,也同样是最难打的(其实都不是很难),接下来我们来谈谈具体算法:
1.适用范围:没有负环(就是走一圈就可以将路程变小,没有最短路的图)的单源最短路(就是只有一个起点的最短路);
2.思路:
已知量只有每条边的权值,但我们可以很容易的想到起点到起点到起点的最短路是0,于是我们可以一开始就将定义一个dij数组来存从起点到每个点的最短路的长度,所以自然dij[1](假设1是起点)就为0,而想要更新其他的就要将除1以外的赋值为MAXN;
因为没有负的权值,所以很容易证明在已有的dij数组中的最小值是不会再被其他点更新的,所以每一次我们都将已有的最短的那个数对应的节点取出,再由它来更新它所连接的点(如果到最小值的那个点的值加上权值依然小于它所连接的那个节点的已有的最小值就更新它),同样不能忘了将这个最小值的点冻结(开个bool数组)以免重复计算;
由于每次取出一个点又冻住那个点,我们不难想到在有n个点的情况下只需要循环n次就行了;
3.操作:
输入:先用邻接表)存下图(注意是单向图还是双向),记录下起点终点;
初值:先memset(dij,0x3f,sizeof(dij)),再将dij[1]赋值为0;
Dijkstra:用一个循环n次的for循环来做取点以及冻结的操作,每次取出最小的点再循环寻找每一个与它相连的节点并更新需要更新的节点;
输出:按题目要求输出;
特殊处理(输出路径):既然都已经找到最短路了那么路径只需要再另开一个数组在更新最短路长度的同时记录是哪一个点更新的它就行了,在最后再用倒推的方式输出即可(可以类比背包问题找方案的方法);
4.例题:
骑车比赛
Description
小信准备去参加骑车比赛,比赛在 n 个城市间进行,编号从 1 到 n。选手们都从城市 1 出发,终点在城市 n。
已知城市间有 m 条道路,每条道路连接两个城市,注意道路是双向的。现在小信知道了他经过每条道路需要花费的时间,他想请你帮他计算一下,他这次比赛最少需要花多少时间完成。
Input
第一行输入两个整数 n,m(1≤n≤1,000,1≤m≤5,000),分别代表城市个数和道路总数。接下来输入 m 行,每行输入三个数字 a,b,c(1≤a,b≤n,1≤c≤200),分别代表道路的起点和道路的终点,以及小信骑车通过这条道路需要花费的时间。保证输入的图是连通的。
Output
输出一行,输出一个整数,输出小信完成比赛需要的最少时间。
Sample Input 1
5 6
1 2 2
2 3 3
2 5 5
3 4 2
3 5 1
4 5 1
Sample Output 1
6
Dijkstra的经典例题(裸题),思路就不在赘述,直接上代码:
代码1(无优化):
#include<bits/stdc++.h>using namespace std;struct node//结构体代表每个节点的数据 ;{int to,ti;//to代表到达的节点,ti代表所需时间 ;node(int a,int b)//构造函数(不会可以不用){to=a;ti=b;}node(){}};int main(){int n,m,x,y,z;cin>>n>>m;map<int,vector<node> > ma;//用映射来存节点以及的其对应的边 ;for(int i=1;i<=m;i++){cin>>x>>y>>z;ma[x].push_back(node(y,z));//注意本题是双向图 ;ma[y].push_back(node(x,z));}int st=1,dis[n+1],vis[n+1];//st代表目前最小的值的节点一开始当然是1;memset(dis,0x3f,sizeof(dis));//先赋一个极大值 ;memset(vis,0,sizeof(vis));//表示是否冻结了节点 ;dis[1]=0;//起点为0;for(int j=1;j<=n;j++)//循环取(冻)点 ;{//cout<<st<<endl;int minn=1e+8,tmp;vis[st]=1;//冻结节点 ;int l=ma[st].size();for(int i=0;i<l;i++)//枚举、更新 ;{if(!vis[ma[st][i].to]){dis[ma[st][i].to]=min(dis[ma[st][i].to],dis[st]+ma[st][i].ti);}}for(int i=1;i<=n;i++)//找已有的最小值 ;{if(!vis[i]&&dis[i]<minn){minn=dis[i];tmp=i;}}st=tmp;//更新 ;}cout<<dis[n];}
我们再仔细读代码便可以发现,找最小值的操作会浪费大量时间(O(n)),那可不可以优化成O(1)呢??我们可以用一个神奇的数据类型——set,set有一个天然排序的性质,我们称这种优化为堆优化;
堆优化代码:
#include<bits/stdc++.h>using namespace std;struct node//结构体代表每条边的数据 ;{int to,q,next;//to表示边连接的节点,q代表权值,next代表这条边的下一个边 ;node(int a,int b,int c){to=a;q=b;next=c;}node(){}}ma[1000001];//ma用于存边 ;set<pair<int,int> > st;//优化的set,分别存dij[i]和i ;int k,head[1000001],dij[1000001],n,m;//head表示每一个节点,由head找到节点对应的边 ;bool ok[1000001];void add(int a,int b,int c)//用于存a到b用c时间的边{ma[++k]=node(b,c,head[a]);head[a]=k;}int main(){memset(dij,0x3f,sizeof(dij));memset(head,-1,sizeof(head));cin>>n>>m;for(int i=1;i<=m;i++){int x,y,z;cin>>x>>y>>z;add(x,y,z);add(y,x,z);}dij[1]=0;st.insert(make_pair(0,1));for(int i=1;i<=n;i++){int u=st.begin()->second;//->为指针找到最小值的节点 ;ok[u]=1;//冻结节点st.erase(st.begin());//删除节点for(int j=head[u];~j;j=ma[j].next)//~j表示j是否为-1 ;{if(!ok[ma[j].to]&&dij[u]+ma[j].q<dij[ma[j].to]){st.erase(make_pair(dij[ma[j].to],ma[j].to));dij[ma[j].to]=ma[j].q+dij[u];st.insert(make_pair(dij[ma[j].to],ma[j].to));}}}cout<<dij[n];}
迪杰斯特拉(Dijkstra) —— 最短路算法相关推荐
- 数据结构与算法(7-4)最短路径(迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法)
目录 一.最短路径概念 二.迪杰斯特拉(Dijkstra)算法(单源最短路径) 1.原理 2.过程 3.代码 三.弗洛伊德(Floyd)算法(多源最短路径) 1.原理 2.存储 3.遍历 4.代码 参 ...
- 059.迪杰斯特拉(Dijkstra)算法的原理以及解决最短路径问题
1. 迪杰斯特拉(Dijkstra)算法的原理 1.1. 算法应用场景-最短路径问题 1.2. 基本介绍 1.3. 步骤详解 1.4. 思路解析 1.5. 图解步骤 2. 迪杰斯特拉(Dijkstra ...
- java数据结构和算法——迪杰斯特拉(Dijkstra)算法
目录 一.迪杰斯特拉(Dijkstra)算法介绍 二.迪杰斯特拉(Dijkstra)算法过程 三.迪杰斯特拉(Dijkstra)算法--应用场景(最短路径问题) 四.迪杰斯特拉(Dijkstra)算法 ...
- 迪杰斯特拉(Dijkstra)算法解决最短路径问题
Dijkstra 算法介绍 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法.迪杰斯特拉(Dijkstra)算法是最经典的最短路径算法之一,用 ...
- c语言迪杰斯特拉算法求最短路径,迪杰斯特拉 ( Dijkstra ) 最短路径算法
迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径.它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法
最短路径算法-迪杰斯特拉(Dijkstra)算法 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思 ...
- Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...
- java实现迪杰斯特拉(Dijkstra)算法求解最短路问题
迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的.是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题. 迪杰斯特拉算法采用贪心算法的策略,将所有顶点分 ...
- 数据结构——图——迪杰斯特拉(Dijkstra )算法
数据结构--图--迪杰斯特拉(Dijkstra )算法 这是一个按路径长度递增的次序产生最短路径的算法.它的思路大体是这样的. 比如说要求图7-7-3中顶点v0到顶点v1的最短距离,没有比这更简单的了 ...
最新文章
- 开源数据库技术分享及未来展望|CIC 真·全明星阵容
- python语音引擎深度学习_python深度学习之语音识别(speech recognize)
- Windows下安装和配置tomca(免安装版本)
- text type dropdown list - INIT_DATA
- java并发练习之快乐影院
- Makefile (二)
- PowerDesigner从数据库导入
- 解决seaborn绘制热力图使用科学记数法
- PhpStorm 中切换PHP版本
- 基于深度极限学习机DELM的回归预测
- linux运维工程师的发展,Linux运维工程师发展前景
- 武汉理工大学计算机学院宿舍,武汉理工大学专业所属校区及新生住宿分布情况(v2.0)...
- 鲁百年创新设计思维学习总结
- 摩根大通的企业级区块链解决方案—Quorum
- 国内首台商用人形双足机器人发展史
- 做了两年前端开发,平时就是拿 Vue 写写页面和组件,简历的项目经历应该怎么写得好看?
- GDOUCTF比赛WEBCRYPTO方向全解!!
- 智能电视是否是一台计算机,误区四 智能电视代替电脑使用_平板电视_液晶电视评测-中关村在线...
- lammps教程:实例讲解npt、nvt系综的选择
- HTML+CSS系列学习