一、问题描述:

给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数。再给定 V 中的一个顶点,称为源,计算源到所有顶点的最短距离。

实例:单源最短路径(弱化版)https://www.luogu.org/problemnew/show/P3371

二、 求取过程:

1. 从起点开始,查找所有与起点直接相连的点,并把连接它们的边权值作为起点到它们的距离(有平行边取最小值)。起点到起点的距离为0,其它不与起点直接相连的点距离为无穷大,存入上图所示的表中。

2. 遍历所有点,查找得到的结果中距离最小的那个点,然后再看所有与该点直接相连的点,计算该点到它们的最短距离(即从起点开始,经由该点到达的点的距离),根据结果更新上图。

3. 不断重复2中过程,直到每一个点都像2中那样计算过一遍。

觉得抽象的话可以看视频:https://www.bilibili.com/video/av2156069

三、合理性:

假设A到C经过B,如果最短路径经过B,那么此时A到B的路径必定最短。

对于第一次操作,我们已经确定了从起点直接到所有点的最短距离。

此时取距离的最小值,有两种情况,一种是最小值来自跳过中间点的直接路径,那么我们可知从起点到该点的最短距离一定来自该路径,因为所有中间点的距离已经比其大,标记该点,已经使用过,接下来该点连接的点也可以根据该点的距离来处理了,因为此时A到B的距离已经最短,且中间点也不会对再对该点产生影响。另一种是最小值来自某一中间路径,那么经过该点的操作,完全有可能使第一次操作得到的距离改变,这就是取最小值的意义。若在未确定某一点最短距离的情况下对该点进行处理,由于该点已经标记使用,那么后续即使该点最短距离改变了,也无法改变该点已经确定的点的情况了。

如图所示的情况,第一次操作后我们知道直接与1相连的点有2, 3, 4。

如果此时不取最小值,例如对4进行处理,那么5的距离直接被确定为10000,此时4被标记使用,后续我们即使通过2,3改变了4的最短距离,5的距离也无法进行改变了。

 四、算法实现:

1. 单源最短路径(弱化版)https://www.luogu.org/problemnew/show/P3371

首先要知道怎么建图:

#include<bits/stdc++.h>using namespace std;const int N=1e6+5;
const int MAX=2147483647;struct node{        //建图(链式向前星,二维矩阵会炸),储存边int from;int to;int value;int next;
}edge[200005];
int head[N];        int dis[N];        //记录每一个顶点的距离
int visited[N];    //记录是否访问过某一个顶点int main()
{int n,m,s;int cnt=0;scanf("%d%d%d",&n,&m,&s);for(int i=1;i<=n;i++) dis[i]=MAX;    //距离初始化为无穷大memset(head,0,sizeof(head));         //这两行其实可以不要memset(visited,0,sizeof(visited));for(int i=1;i<=m;i++)    //建图,储存边{cnt++;scanf("%d%d%d",&edge[cnt].from,&edge[cnt].to,&edge[cnt].value);int from=edge[cnt].from;int to=edge[cnt].to;edge[cnt].next=head[from];head[from]=cnt;}int start=s;            //以s为起点dis[start]=0;           //起点到自己的距离为0while(visited[start]!=1)    //开始模拟查找过程{visited[start]=1;    //标记该起点,表示已访问过for(int i=head[start];i!=0;i=edge[i].next)    //读取与起点相连的边{if(dis[edge[i].to]>dis[start]+edge[i].value)    //算法的核心dis[edge[i].to]=dis[start]+edge[i].value;}int minn=MAX;            //每一次都寻找所有点中距离最小的点for(int i=1;i<=n;i++){if(visited[i]!=1 && minn>dis[i]){minn=dis[i];start=i;        //以距离最小的点为新的起点,开始查找}}}for(int i=1;i<=n;i++){if(i==n) printf("%d\n",dis[i]);else printf("%d ",dis[i]);}
}

2. 单源最短路径(标准版):https://www.luogu.org/problemnew/show/P4779

这题数据要比上一题大,所以要进行优化。

上一题的写法每一次都要查找距离最短的点,占用了大量时间,我们用优先队列优化这个过程。

有关优先队列可参考:https://blog.csdn.net/qq_19656301/article/details/82490601

#include <bits/stdc++.h>using namespace std;const int N=1e5+5;
const int MAX=2147483647;
typedef long long LL;struct node{        //建图部分还是一样的int from;int to;int value;int next;
}edge[2*N];
int head[N];LL dis[N];
int visited[N];priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >vis;    //优先队列int main()
{int n,m,s;int cnt=0;cin>>n>>m>>s;for(int i=1;i<=n;i++) dis[i]=MAX;for(int i=1;i<=m;i++){cnt++;scanf("%d%d%d",&edge[cnt].from,&edge[cnt].to,&edge[cnt].value);edge[cnt].next=head[edge[cnt].from];head[edge[cnt].from]=cnt;}dis[s]=0;vis.push(make_pair(0,s));    //储存某点距离和该点//make_pair是c++自带的二元组定义方式,可以通过first、second访问第一个,第二个元素(小根堆以第一个值排序)while(!vis.empty())        //判断所有点是否都查找过一遍{int start=vis.top().second;    //优先队列队首即最小的元素vis.pop();if(visited[start]==1) continue;    //如果该点查找过,跳过visited[start]=1;for(int i=head[start];i!=0;i=edge[i].next){if(dis[edge[i].to]>dis[start]+edge[i].value){dis[edge[i].to]=dis[start]+edge[i].value;vis.push(make_pair(dis[edge[i].to],edge[i].to));     }}}for(int i=1;i<=n;i++){if(i==n) printf("%d\n",dis[i]);else printf("%d ",dis[i]);}
}

单源最短路径问题-迪杰斯特拉算法(Dijsktra)相关推荐

  1. 数据结构之单源最短路径(迪杰斯特拉算法)-(九)

    最开始接触最短路径是在数据结构中图的那个章节中.运用到实际中就是我在大三参加的一次美赛中,解决中国的水资源问题.所谓单源最短路径,就是一个起点到图中其他节点的最短路径,这是一个贪心算法. 迪杰斯特拉算 ...

  2. 单源最短路径之迪杰斯特拉算法(C语言)

    Dijkstra(迪杰斯特拉)算法 采用广度优先搜索思想,对有向赋权图寻找最短路径. 该算法对于不含负权的有向图来说,是目前已知的最快的单源最短路径算法. 时间复杂度:O(n^2) 基本原理:不断为为 ...

  3. 单源最短路径算法java_数据结构 - 单源最短路径之迪杰斯特拉(Dijkstra)算法详解(Java)...

    给出一个图,求某个端点(goal)到其余端点或者某个端点的最短路径,最容易想到的求法是利用DFS,假设求起点到某个端点走过的平均路径为n条,每个端点的平均邻接端点为m,那求出这个最短路径使用DFS算法 ...

  4. 图的应用——最短路径(迪杰斯特拉算法)

    Content 1. 什么是最短路径 2. 迪杰斯特拉算法[O(n^2^)] 3. 代码 4. 迪杰斯特拉算法 VS 普利姆算法 1. 什么是最短路径 在一个带权有向图中,从某一顶点到另一顶点可能有很 ...

  5. (王道408考研数据结构)第六章图-第四节4:最短路径之迪杰斯特拉算法(思想、代码、演示、答题规范)

    文章目录 一:BFS算法局限性 二:迪杰斯特拉(dijkstra)算法基本思想 三:迪杰斯特拉(dijkstra)算法代码实现 四:迪杰斯特拉(dijkstra)算法代码视频演示 五:迪杰斯特拉(di ...

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

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

  7. 图的最短路径之迪杰斯特拉算法和弗洛伊德算法

    文章目录 一.迪杰斯特拉(Dijkstra)算法 1.定义描述 2.算法思想 3.算法步骤 4.算法图解 二.弗洛伊德(Floyd)算法 1.定义描述 2.算法思想 3.算法步骤 三.Dijkstra ...

  8. 最短路径之迪杰斯特拉算法

    基本思想: 设置顶点集合S并不断地作贪心选择来扩充这个集合.一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知. 初始时,S中仅含有源.设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称 ...

  9. 最短路径(迪杰斯特拉算法)

    1 构造图 2 代码 package leaning.graph;/** 迪杰斯特拉算法求最短路径* * */ public class Dijkstra {// 表示V0顶点到v8顶点的最短路径的值 ...

最新文章

  1. 让Windows下的Tomcat将控制台信息记录到日志
  2. 用jQuery预加载图像
  3. 分享:几款代码混淆器(DotFuscator, .NET Reactor, xenocode)
  4. 2018上半年软件设计师上午题参考答案
  5. mybatisplus批量插入原理_【学习】热转印工艺原理、特点及工艺流程
  6. ReportViewer教程(15)-矩阵报表-5
  7. json转excel_如何快速把json数据转到excel表格,方便个人查看
  8. 【CF 736C】Ostap and Tree,树形DP
  9. 苹果手机投屏到电脑大屏幕上的方法
  10. 8cm等于多少像素_像素和厘米如何换算
  11. Dilworth 定理
  12. SpringCloud_Dubbo_JZZ_MBY
  13. salesforce中常用技能总结(纯粹干货,深度积累)图解
  14. button控件具体用法(CommandName, CommandArgument)
  15. 百度搜索引擎优化指南 2.0
  16. [团队项目]用户需求文档发布!
  17. 知识 | 什么是相控阵雷达?
  18. word 直接插入参考文献,不借助插件
  19. 《数学分析新讲》_张筑生,12.5节:隐函数定理(2)
  20. wps控件属性怎么用_WPS表格怎么使用列表框控件?

热门文章

  1. 自由自在亮法宝 远离流感提升免疫力
  2. 安全性归约(安全性定义 - 1)
  3. 去掉flash builder生成apk时候自动加air前缀的方法
  4. VS中怎么调出资源方案管理器
  5. 2022年质量团队发展规划(软件测试方向)
  6. (十四、SchoolAdmin 模块实现)莞工校招助手【微服务应用】
  7. 轮播图为什么不显示?
  8. 营销革命5.0—用技术手段推动市场部变革
  9. 2021年甘肃省安全员B证考试报名及甘肃省安全员B证免费试题
  10. 苹果6s照相快门声音设置_你不知道的8种手机快门启动方式,各有妙用!