做OJ需要用到搜索最短路径的题,于是整理了一下关于图的搜索算法:

图的搜索大致有三种比较常用的算法:

  • 迪杰斯特拉算法(Dijkstra算法)
  • 弗洛伊德算法(Floyd算法)
  • SPFA算法

Dijkstra算法使用了广度优先搜索解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。

算法的思路:

Dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s。
然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点,
然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。
然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。

举例:

下面我求下图,从顶点v1到其他各个顶点的最短路径

首先第一步,我们先声明一个dis数组,该数组初始化的值为:

我们的顶点集T的初始化为:T={v1}

既然是求 v1顶点到其余各个顶点的最短路程,那就先找一个离 1 号顶点最近的顶点。通过数组 dis 可知当前离v1顶点最近是 v3顶点。当选择了 2 号顶点后,dis[2](下标从0开始)的值就已经从“估计值”变为了“确定值”,即 v1顶点到 v3顶点的最短路程就是当前 dis[2]值。将V3加入到T中。
为什么呢?因为目前离 v1顶点最近的是 v3顶点,并且这个图所有的边都是正数,那么肯定不可能通过第三个顶点中转,使得 v1顶点到 v3顶点的路程进一步缩短了。因为 v1顶点到其它顶点的路程肯定没有 v1到 v3顶点短.

OK,既然确定了一个顶点的最短路径,下面我们就要根据这个新入的顶点V3会有出度,发现以v3 为弧尾的有: < v3,v4 >,那么我们看看路径:v1–v3–v4的长度是否比v1–v4短,其实这个已经是很明显的了,因为dis[3]代表的就是v1–v4的长度为无穷大,而v1–v3–v4的长度为:10+50=60,所以更新dis[3]的值,得到如下结果:

因此 dis[3]要更新为 60。这个过程有个专业术语叫做“松弛”。即 v1顶点到 v4顶点的路程即 dis[3],通过 < v3,v4> 这条边松弛成功。这便是 Dijkstra 算法的主要思想:通过“边”来松弛v1顶点到其余各个顶点的路程。

然后,我们又从除dis[2]和dis[0]外的其他值中寻找最小值,发现dis[4]的值最小,通过之前是解释的原理,可以知道v1到v5的最短距离就是dis[4]的值,然后,我们把v5加入到集合T中,然后,考虑v5的出度是否会影响我们的数组dis的值,v5有两条出度:< v5,v4>和 < v5,v6>,然后我们发现:v1–v5–v4的长度为:50,而dis[3]的值为60,所以我们要更新dis[3]的值.另外,v1-v5-v6的长度为:90,而dis[5]为100,所以我们需要更新dis[5]的值。更新后的dis数组如下图:

然后,继续从dis中选择未确定的顶点的值中选择一个最小的值,发现dis[3]的值是最小的,所以把v4加入到集合T中,此时集合T={v1,v3,v5,v4},然后,考虑v4的出度是否会影响我们的数组dis的值,v4有一条出度:< v4,v6>,然后我们发现:v1–v5–v4–v6的长度为:60,而dis[5]的值为90,所以我们要更新dis[5]的值,更新后的dis数组如下图:

然后,我们使用同样原理,分别确定了v6和v2的最短路径,最后dis的数组的值如下:

因此,从图中,我们可以发现v1-v2的值为:∞,代表没有路径从v1到达v2。所以我们得到的最后的结果为:

起点  终点    最短路径    长度
v1    v2     无          ∞    v3     {v1,v3}    10v4     {v1,v5,v4}  50v5     {v1,v5}    30v6     {v1,v5,v4,v6} 60

转载自Ouyang_Lianjun的博客。

利用上述思路结题TjuOj 2870题目和代码如下:

Given a map of your country, there are N cities. The cities are labeled as 0, 1, ..., N - 1, and you live in city 0. Can you calculate out the K-th nearest city form you? If two or more cities have the same distance form you, you may assume that the city with smaller label is nearer than the city with bigger one.

Input

There are several cases. The first line of each case is two integers N and M (1 ≤ N ≤ 200, 0 ≤ M ≤ 10000), which is the number of cities in your country and the total number of roads in your country. There are three integers in each of the following M lines, ABC, which descript one road. A and B are the two cities that connected by that road, and C is the length of that road (1 ≤ C ≤ 2000). The roads are of both directions, and no two roads connect two same cities. There is at least one path between any two cities. At the last line of each case is a single integer K (1 ≤ K < N).

The last case is followed by a line with a single 0.

Output

Print the label of the K-th nearest city.

/** 2870*   利用迪杰斯特拉克算法找单一源点出发的最短路径*  Created on: 2018年11月15日*      Author: Jeason*/
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define inf 999999999int n, q;
int g[210][210];  //存放边的数组
int d[210];   //待求距离的数组
int vis[210];   //标记是否已访问void Dijkstra(int k) {int i, j;for (i = 0; i < n; i++) {d[i] = inf;    //带求距离的数组
    }d[0] = 0;        //第一个点的距离到源点距离为0;memset(vis, 0, sizeof(vis));  //初始化访问标记数组(未被发现最短路径的点);int cnt = -1;int ans;for (i = 0; i < n; i++) {   //遍历N次,每次找到一个点到源点的最短路径;int Min = inf;    //最小值初始化正无穷int pos = -1;      //本次认为离远点最近的位置,初始化for (j = 0; j < n; j++) if (!vis[j]) {    //对每一个正在遍历的点,遍历相连的其他点(未被发现最短路径的点)if ( d[j] < Min ) {           //找当前最小的值Min = d[j];pos = j;

            }}cnt++;     //标记循环次数,每次找到一个稍微远一点的点if (cnt == k) {ans = pos;break;}vis[pos] = 1;for (j = 0; j < n; j++) {   //更新已经找到最近点后,通过该点其附近相连的点会不会比源点直接到该点近。if ( d[pos] + g[pos][j] < d[j]) {d[j] = g[pos][j] + d[pos];}}}cout << ans << endl;
}int main() {int i, j;while (cin >> n) {   //读进来n个点if (n == 0) break;for (i = 0; i < n; i++) {    //把长度初始化最大for (j = 0; j < n; j++) {g[i][j] = inf;}}scanf("%d", &q);    //读入q条边for (i = 1; i <= q; i++) {int a, b, c;cin >> a >> b >> c;if (g[a][b] > c) {g[a][b] = g[b][a] = c;}}int k;scanf("%d", &k);Dijkstra(k);}return 0;
}/*
Sample Input
4 3
0 1 120
0 2 180
1 3 40
3
4 3
0 1 120
0 3 60
3 2 30
1
0
Sample Output
2
3
*/

转载于:https://www.cnblogs.com/JeasonIsCoding/p/9964963.html

图的最短路径-----------Dijkstra算法详解(TjuOj2870_The Kth City)相关推荐

  1. Dijkstra算法详解(完美图解、趣学算法)

    Dijkstra算法详解 Dijkstra算法设计 Dijkstra算法简介 Dijkstra算法的基本思想 Dijkstra贪心策略 完美图解 伪代码详解 完整代码 算法解析及优化拓展 使用优先队列 ...

  2. python棋盘最短路径_Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例...

    本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...

  3. 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?...

    简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...

  4. 迪杰斯特拉(Dijkstra)算法详解

    迪杰斯特拉(Dijkstra)算法详解 在讲解迪杰斯特拉算法之前先讲解一下什么是最短路径: [图一] 假如我要求从A点到D点的最短路径,我们用肉眼可以很快速找出A–>C–>E–>D就 ...

  5. 图论-最短路Dijkstra算法详解超详 有图解

    整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...

  6. 【数据结构】图(最短路径Dijkstra算法)的JAVA代码实现

    最短路径的概念 最短路径的问题是比较典型的应用问题.在图中,确定了起始点和终点之后,一般情况下都可以有很多条路径来连接两者.而边或弧的权值最小的那一条路径就称为两点之间的最短路径,路径上的第一个顶点为 ...

  7. dijkstra 算法_最短路径问题Dijkstra算法详解

    1.Dijkstra算法介绍 · 算法起源: · Djkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家E ...

  8. 解决最短路径的Dijkstra算法详解,附加Java代码

    1. 最短路径问题 最短路径问题是生活中经常碰到的一类问题,如机器人路径规划,数学竞赛以及真实的工程施工问题:甚至是我们程序员笔试必刷算法题.其实问题很简单,就是有很多个节点,我们要计算出一个初始点到 ...

  9. 最短路径问题 --- Dijkstra算法详解

    最短路径问题 最短路径问题 1.最短路径问题介绍 2.Dijkstra 算法思路 3.Dijkstra算法示例演示 4.Dijkstra算法的代码实现(c++) 参考 最短路径问题 1.最短路径问题介 ...

  10. 最短路径问题:Dijkstra算法详解

    前言  Nobody can go back and start a new beginning,but anyone can start today and make a new ending.  ...

最新文章

  1. SharpDevelop源码分析 (一、序+基本概念) 收藏
  2. why always WebContent is added as prefix of url when repository request served
  3. C#刷剑指Offer | 【常考题】最小的k个数
  4. BZOJ.4516.[SDOI2016]生成魔咒(后缀自动机 map)
  5. 【牛客 - 1080E】tokitsukaze and Segmentation(dp,递推,思维)
  6. 《Python数据分析》第二版.第二章.[学习笔记][Jupyter notebook]
  7. python中文版软件下载-Python中文版下载_PyCharm官方最新版下载_3DM单机
  8. Base64转BufferedImage
  9. 【SecureCRT的下载、安装与使用】详细过程
  10. 浅谈人机关系在生活中的应用
  11. 信号与系统 基础知识点整理 01(文末可下载PDF格式)
  12. arduino 超声波测距原理_[Arduino]超声波测距
  13. Spring Boot整合Admin
  14. js实现oss批量下载文件_前端实现批量打包下载文件
  15. 用java模拟csma_CSMA/CD仿真的过程
  16. 什么是子网掩码,如何判断两个IP是不是同一网段
  17. “华为 30 岁以下员工仅占 28%”上热搜,网友:说好的 35 岁天花板呢?
  18. ISMS整体项目进度表
  19. 2743: [HEOI2012]采花(离线树状数组)
  20. 【CMake 项目】CMake 项目、目标、子目录

热门文章

  1. 冒着被开除的风险也要给大家看看看这份Spring Cloud 总结
  2. 在同一个公司死磕5-10年,到底值不值得?
  3. 今日头条首次公开算法原理(附全文详解)
  4. Go语言构建高并发分布式系统实践
  5. 普通人在互联网还有机会么?
  6. hdu 2844 Coins (多重背包+二进制优化)
  7. bzoj1612 奶牛的比赛
  8. 漫画:女生/男生告白攻略
  9. Java里多个Map的性能比較(TreeMap、HashMap、ConcurrentSkipListMap)
  10. Android开发工程师,前行路上的14项技能