详解Dijkstra算法原理及其C++实现

详解Dijkstra算法原理及其C++实现

前言

Dijkstra算法是一种常见的求解单源最短路径的算法,本文将对其进行详细的讲解。

原理

Dijkstra算法的核心思想是贪心,即每次都选择当前最短路径上距离起点最近的顶点,并通过该顶点更新与其相邻的顶点的距离。Dijkstra算法使用一个数组dist[i]来记录起点到每个顶点的最短距离,同时使用一个visited[i]数组来记录每个顶点是否被访问过。

具体步骤可概括为:

  1. 初始化:将起点s加入集合S,将起点到每个顶点的距离dist[i]初始化为无穷大,将visited[i]初始化为false。
  2. 更新:从集合V-S中选择距离起点s最近的顶点u,将u加入集合S,对于与u相邻的顶点v,若dist[u]+w(u,v)<dist[v],则更新dist[v]=dist[u]+w(u,v),其中w(u,v)表示边(u,v)的权值。
  3. 重复进行步骤2,直到所有顶点都被加入集合S。

Dijkstra算法的时间复杂度为O(n^2),但可以通过堆优化的方式将其优化到O(nlogn)。

C++实现

以下是Dijkstra算法的C++实现代码:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

const int MAXN = 1005;
const int INF = 0x3f3f3f3f;

int dist[MAXN], visited[MAXN];
vector<pair<int, int>> G[MAXN];

void Dijkstra(int s) {
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
    memset(dist, INF, sizeof(dist));
    dist[s] = 0;
    q.push({0, s});

    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        if (visited[u]) continue;
        visited[u] = 1;
        for (auto& v : G[u]) {
            int d = v.second;
            if (dist[v.first] > dist[u] + d) {
                dist[v.first] = dist[u] + d;
                if (!visited[v.first]) q.push({dist[v.first], v.first});
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;

    for (int i = 1; i <= m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u].push_back({v, w});
        G[v].push_back({u, w});
    }

    int s;
    cin >> s;
    Dijkstra(s);

    for (int i = 1; i <= n; i++) {
        if (dist[i] == INF) cout << "INF" << endl;
        else cout << dist[i] << endl;
    }

    return 0;
}

示例说明

示例1

输入:

5 6
1 2 10
1 3 5
2 4 1
3 4 2
3 5 1
4 5 4
1

输出:

0
5
7
6
10

解释:

该图如下所示:

1 --10-- 2
|\     /
| 5\  /1
|   \/
|   /\
|2/   \4
v/     \
3 --2-- 5

起点为1,最短路径如下:

  • 1->2: 10
  • 1->3: 5
  • 1->4->2: 11
  • 1->4->3: 7
  • 1->4->5: 10

因此,输出结果为0 5 7 11 10。

示例2

输入:

4 4
1 2 3
1 3 5
2 4 4
3 4 2
1

输出:

0
3
5
7

解释:

该图如下所示:

1 --3-- 2
|\     /
| 5\  /4
|   \/
|   /\
|2/   \4
v/     \
3 --2-- 4

起点为1,最短路径如下:

  • 1->2: 3
  • 1->3: 5
  • 1->2->4: 7
  • 1->3->4: 7

因此,输出结果为0 3 5 7。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Dijkstra算法原理及其C++实现 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • PHP的JSON封装、转变及输出操作示例

    针对PHP的JSON封装、转变及输出操作,下面给出完整的攻略。 1. JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写。它是由Douglas Crockford发明的,目前已成为互联网数据交换中十分流行的标准格式之一。JSON格式有两种数据结构,分别是对象和数组。 2. PHP中JSON…

    C 2023年5月23日
    00
  • 企业官网怎么做 5大设计要点教你搭建好看又好卖的企业产品官网

    下面是讲解“企业官网怎么做 5大设计要点教你搭建好看又好卖的企业产品官网”的完整攻略。 1. 设计风格 企业官网的设计风格应当符合企业的品牌形象与企业文化,传达出企业的特点与业务重点。因此,设计风格应当与企业的行业和定位相符合,同时重视用户体验,为用户提供方便快捷的浏览体验。 2. 导航设计 导航设计要符合网站用户习惯,以用户体验为导向,使用户可以轻松找到所…

    C 2023年5月23日
    00
  • 电脑出现错误代码:0xc000007b最全最详细的解决办法

    针对电脑出现错误代码:0xc000007b,以下是详细的解决办法: 问题描述 当电脑启动或运行某些程序时,会出现错误代码:0xc000007b,导致程序无法正常运行或闪退。 解决方案 方案一:安装缺失的组件 错误代码:0xc000007b通常是由于缺少相关运行库和组件引起的。可以前往Microsoft官网下载安装Visual C++、.NET Framewo…

    C 2023年5月22日
    00
  • 一篇文章教你用Java使用JVM工具检测问题

    一篇文章教你用Java使用JVM工具检测问题 1. 前言 在Java开发过程中,我们常常会遇到一些问题,比如程序运行慢、内存占用过高等等。这些问题往往与JVM密不可分,而如何使用JVM工具进行问题检测,是每个Java开发者都应该掌握的技能。 本篇文章将带你从零开始,详细讲解如何使用Java自带的JVM工具进行问题检测。 2. 使用JVM工具检测问题的基本流程…

    C 2023年5月22日
    00
  • C++算法学习之贪心算法的应用

    C++算法学习之贪心算法的应用 算法简介 贪心算法是一种算法思想,指的是在求解问题时,总是做出当前看来最优的选择,也就是说在每一步中都选择最优解,最终得到全局最优解。 贪心算法的优点在于其简单易懂、运行效率高等特点。但是,由于贪心算法对于求解问题的约束条件和目标函数的要求过高,导致其只能解决部分问题,无法求解所有NP问题。一般情况下,合理的贪心策略是求解问题…

    C 2023年5月22日
    00
  • C++如何将二叉搜索树转换成双向循环链表(双指针或数组)

    将二叉搜索树转换成双向循环链表是一道比较经典的算法题,本文将对该算法进行完整讲解。 算法思路 我们可以将该问题划分成多个子问题:- 将左子树转换为双向循环链表,并返回链表头和链表尾;- 将右子树转换为双向循环链表,并返回链表头和链表尾;- 将当前节点插入左子树的链表尾,将左子树链表尾连接至当前节点;- 将当前节点插入右子树的链表头,将右子树链表头连接至当前节…

    C 2023年5月23日
    00
  • Go/C语言LeetCode题解997找到小镇法官

    下面是关于“Go/C语言LeetCode题解997找到小镇法官”的完整攻略: 题目描述 在一个小镇里,按从1到N标记了N个人。传言中,这些人中有一个是小镇上的法官。如果小镇的法官真的存在,请你找出他并返回其编号;否则,返回-1。 注意: 要求时间复杂度O(N),空间复杂度O(1); 1 <= N <= 1000; trust[i]是一个长度为2的…

    C 2023年5月22日
    00
  • 详解JavaScript中数组的一些特殊用法

    详解JavaScript中数组的一些特殊用法 数组是JavaScript中最重要的数据类型之一,其具有存储一组有序数据的能力。常见的操作包括遍历、添加、删除、排序、查找等。而除此之外,数组还有一些特殊的用法,可以让我们更好地处理数据或进行编程。 数组去重 数组去重是数组操作中的一个常见需求,我们可以使用ES6中的Set来实现简单的去重。 const arr …

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部