做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}
v4 {v1,v5,v4}
v5 {v1,v5}
v6 {v1,v5,v4,v6}

转载自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 999999999 int n, q;
int g[][]; //存放边的数组
int d[]; //待求距离的数组
int vis[]; //标记是否已访问 void Dijkstra(int k) {
int i, j;
for (i = ; i < n; i++) {
d[i] = inf; //带求距离的数组
}
d[] = ; //第一个点的距离到源点距离为0;
memset(vis, , sizeof(vis)); //初始化访问标记数组(未被发现最短路径的点);
int cnt = -;
int ans;
for (i = ; i < n; i++) { //遍历N次,每次找到一个点到源点的最短路径;
int Min = inf; //最小值初始化正无穷
int pos = -; //本次认为离远点最近的位置,初始化
for (j = ; j < n; j++) if (!vis[j]) { //对每一个正在遍历的点,遍历相连的其他点(未被发现最短路径的点)
if ( d[j] < Min ) { //找当前最小的值
Min = d[j];
pos = j; }
}
cnt++; //标记循环次数,每次找到一个稍微远一点的点
if (cnt == k) {
ans = pos;
break;
}
vis[pos] = ;
for (j = ; 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 == ) break;
for (i = ; i < n; i++) { //把长度初始化最大
for (j = ; j < n; j++) {
g[i][j] = inf;
}
}
scanf("%d", &q); //读入q条边
for (i = ; 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 ;
} /*
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
*/

图的最短路径-----------Dijkstra算法详解(TjuOj2870_The Kth City)的更多相关文章

  1. 图的最短路径-----------SPFA算法详解(TjuOj2831_Wormholes)

    这次整理了一下SPFA算法,首先相比Dijkstra算法,SPFA可以处理带有负权变的图.(个人认为原因是SPFA在进行松弛操作时可以对某一条边重复进行松弛,如果存在负权边,在多次松弛某边时可以更新该 ...

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

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

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

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

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

    侵删https://blog.csdn.net/qq_35644234/article/details/60870719 前言 Nobody can go back and start a new b ...

  5. Dijkstra算法详解

    1.dijkstra算法简介 Dijkstra算法是由E.W.Dijkstra于1959年提出,又叫迪杰斯特拉算法,它应用了贪心算法模式,是目前公认的最好的求解最短路径的方法.算法解决的是有向图中单个 ...

  6. HDU 1874 畅通工程续-- Dijkstra算法详解 单源点最短路问题

    参考 此题Dijkstra算法,一次AC.这个算法时间复杂度O(n2)附上该算法的演示图(来自维基百科): 附上:  迪科斯彻算法分解(优酷) problem link -> HDU 1874 ...

  7. 八大排序算法详解(动图演示 思路分析 实例代码java 复杂度分析 适用场景)

    一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...

  8. c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法

    c/c++ 图的最短路径 Dijkstra(迪杰斯特拉)算法 图的最短路径的概念: 一位旅客要从城市A到城市B,他希望选择一条途中中转次数最少的路线.假设途中每一站都需要换车,则这个问题反映到图上就是 ...

  9. 数据结构实验之图论七:驴友计划 ( 最短路径 Dijkstra 算法 )

    数据结构实验之图论七:驴友计划 Time Limit: 1000 ms           Memory Limit: 65536 KiB Submit Statistic Discuss Probl ...

随机推荐

  1. PHP密码的六种加密方式

    1. MD5加密 string md5 ( string $str [, bool $raw_output = false ] ) 参数 str  --  原始字符串. raw_output  --  ...

  2. Java中的基本数据据类型

    1.整数类型 类型 字节数 表示范围 byte 1 -128~127 short 2 -32768 ~ 32767 int 4 -2147483648~2147483647 long 8 -92233 ...

  3. Visual Studio(VS)C++单元测试

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Visual Studio(VS)C++单元测试     本文地址:http://techie ...

  4. 11th 回顾5个问题

    当初提出的5个问题: 1.书中说很多非常成功的软件都是赢在用户体验,后面的第12章也专门提到了用户体验,说软件开发时可以使用5W1H的方法来判断用户的体验,而需求分析需要获取用户需求,进行用户调研,那 ...

  5. PAT 甲级 1057 Stack

    https://pintia.cn/problem-sets/994805342720868352/problems/994805417945710592 Stack is one of the mo ...

  6. PAT 甲级 1106 Lowest Price in Supply Chain

    https://pintia.cn/problem-sets/994805342720868352/problems/994805362341822464 A supply chain is a ne ...

  7. js弹出层学习

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  8. 一本通1649【例 2】2^k 进制数

    1649:[例 2]2^k 进制数 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 原题来自:NOIP 2006 提高组 设 r 是个 2k 进制数,并满足以 ...

  9. [代码]--ORA-01843: 无效的月份

    1.插入的日期如果是DateTime类型的,没有影响 2.如果DateTime.ToString()获取的日期,就会报错,例如(@param_datetime = cf.GetServerDateTi ...

  10. 自动化运维工之Ansible(1)

    1.1 ansible简介 1.1.1 .Ansible软件介绍: Ansible提供一种最简单的方式用于发布.管理和编排计算机系统的工具,可在数分钟内搞定.Ansible由Python语言开发, 默 ...