(迪杰斯特拉)Dijkstra算法及其优化(C++)

这篇具有很好参考价值的文章主要介绍了(迪杰斯特拉)Dijkstra算法及其优化(C++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目原文

题目描述
给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。
请你求出 1 1 1 号点到 n n n 号点的最短距离,如果无法从 1 1 1 号点走到 n n n 号点,则输出 − 1 −1 1

输入格式
第一行包含整数 n n n m m m
接下来 m m m 行每行包含三个整数 x , y , z , x,y,z, x,y,z, 表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z

输出格式
输出一个整数,表示 1 1 1 号点到 n n n 号点的最短距离。
如果路径不存在,则输出 − 1 −1 1

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

算法思想

算法背景:

迪杰斯特拉算法是由荷兰计算机科学家在1956年发现的算法,是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。

算法步骤如下:

  1. 初始化过程:初始时令 S = V 0 , T = V − S = S={V_0},T=V-S= S=V0,T=VS= { 其余顶点 },T中顶点对应的距离值:
    若存在, d ( V 0 , V i ) d(V_0,V_i) d(V0,Vi) 为弧上的权值;
    若不存在, d ( V 0 , V i ) d(V0,Vi) d(V0,Vi) ∞ \infty
  2. 选取最短路径过程:从 T T T 中选取一个与 S S S 中顶点有关联边且权值最小的顶点 W W W ,加入到 S S S 中。
  3. 调整邻接点距离过程:对其余 T T T 中顶点的距离值进行修改:若加进 W W W 作中间顶点,从 V 0 V_0 V0 V i V_i Vi 的距离值缩短,则修改此距离值。
    重复上述步骤2、3,直到 S S S 中包含所有顶点,即 W = V i W=V_i W=Vi为止。

算法过程

题目原文 中输入样例为例(蓝色代表 T T T,橙色代表 S S S):
开始时,1在 S S S 中,而2、3在 T T T 中,
(迪杰斯特拉)Dijkstra算法及其优化(C++)

节点 距离
1 0
2 2
3 4

然后将距离为2的边所对应的节点2加入 S S S 中:
(迪杰斯特拉)Dijkstra算法及其优化(C++)

节点 距离
1 0
2 2
3 3

最后将节点3加入 S S S 中:
(迪杰斯特拉)Dijkstra算法及其优化(C++)

节点 距离
1 0
2 2
3 3

算法结束,题目所求节点 1 到节点 n n n 的距离即为 3。

算法代码

  1. 当数据范围满足 1 ≤ n ≤ 500 , 1 ≤ m ≤ 1 0 5 1≤n≤500,1≤m≤10^5 1n500,1m105 时,直接使用朴素算法即可。且图为稠密图,结构直接使用邻接矩阵储存即可。
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 510;

int g[N][N], d[N];
bool st[N];
int n, m;

int  dijkstra()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    
    for (int i = 1; i <= n; i ++ )
    {
        int temp = -1;
        for (int j = 1; j <= n; j ++ )
        {
            if (!st[j] && (temp == -1 || d[j] < d[temp])) temp = j;
        }
        
        for (int j = 1; j <= n; j ++ )
        {
            d[j] = min(d[j], d[temp] + g[temp][j]);
        }
        
        st[temp] = true;
    }
    
    if (d[n] == 0x3f3f3f3f) return -1;
    return d[n];
}

int main()
{
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while (m -- )
    {
        int x, y, z;
        cin >> x >> y >> z;
        g[x][y] = min(g[x][y], z);
    }
    cout << dijkstra() << endl;
    return 0;
}

  1. 当数据范围满足 1 ≤ n , m ≤ 1.5 × 1 0 5 1≤n,m≤1.5×10^5 1n,m1.5×105 时,考虑对算法进行优化。且图为稀疏图,所以采用邻接表存储结构对图进行储存。

优化:原算法时间复杂度为 O ( n 2 ) O(n^2) O(n2) ,我们可以发现,如果边数远小于 n 2 n^2 n2,对此可以考虑用堆这种数据结构对其进行优化,将最耗时的 选取最短路径过程 的复杂度降为O(1);此外,使用堆结构后 调整邻接点距离过程 的复杂度变为 O ( m l o g n ) O(mlogn) O(mlogn);e为该点的边数,所以复杂度降为 O ( m l o g n ) O(mlogn) O(mlogn)
这里使用优先队列 priority_queue 作为堆。文章来源地址https://www.toymoban.com/news/detail-406318.html

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>

using namespace std;

typedef pair<int, int> PII;

const int N = 2e5;

int n, m, idx = -1;
int h[N], ne[N], w[N], e[N];
int d[N];
bool st[N];

void add(int x, int y, int z)
{
    ne[++ idx] = h[x];
    h[x] = idx;
    e[idx] = y;
    w[idx] = z;
}

int dijkstra()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    
    while (!heap.empty())
    {
        auto item = heap.top();
        heap.pop();
        
        int dist = item.first, node = item.second;
        
        if (st[node]) continue;
        st[node] = true;
        
        for (int i = h[node]; i != -1; i = ne[i])
        {
            if (d[e[i]] > dist + w[i]) 
            {
                d[e[i]] = dist + w[i];
                heap.push({d[e[i]], e[i]});
            }
        }
    }
    
    if (d[n] == 0x3f3f3f3f) return -1;
    return d[n];
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);
    while (m -- )
    {
        int x, y, z;
        cin >> x >> y >> z;
        add(x, y, z);
    }
    cout << dijkstra() << endl;
    return 0;
}

到了这里,关于(迪杰斯特拉)Dijkstra算法及其优化(C++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • dijkstra迪杰斯特拉算法(邻接表法)

    算法简易过程: 求单源有向图最短路径 使用 邻接表法 来存储顶点和边,录入 有向图 。 (当然也可以无向图,不过录入时要录入两次,比如 a b 3        b a 3)  代码如下: 测试如下:  

    2024年02月07日
    浏览(42)
  • C语言 最短路径 迪杰斯特拉(Dijkstra)算法

    迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中单源最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最

    2024年02月03日
    浏览(43)
  • 【数据结构】图解:迪杰斯特拉算法(Dijkstra)最短路径

    目录 一、方法描述 二、例题一  ​编辑 三、例题二  有图如上,用迪杰斯特拉算法求顶点A到其余各顶点的最短路径,请问1.第一步求出的最短路径是A到C的最短路径2.第二步求出的是顶点A到顶点B/F的最短路径3.顶点A到D的最短路径长度是__25___ (填数字)4.顶点A到顶点F的最短路

    2024年02月12日
    浏览(36)
  • java实现迪杰斯特拉(Dijkstra)算法求解最短路问题

    迪杰斯特拉(Dijkstra)算法是由荷兰计算机科学家狄克斯特拉于1959年提出的。是寻找从一个顶点到其余各顶点的最短路径算法,可用来解决最短路径问题。 迪杰斯特拉算法采用贪心算法的策略,将所有顶点分为已标记点和未标记点两个集合,从起始点开始,不断在未标记点中寻

    2024年02月12日
    浏览(40)
  • 大话数据结构-迪杰斯特拉算法(Dijkstra)和弗洛伊德算法(Floyd)

      最短路径,对于图来说,是两顶点之间经过的边数最少的路径;对于网来说,是指两顶点之间经过的边上权值之和最小的路径。路径上第一个顶点为源点,最后一个顶点是终点。   以如下无向图为例:   我们来计算下标为0的顶点,到其他顶点的最短路径,首先定义

    2024年02月06日
    浏览(41)
  • 数据结构 -最短路径dijkstra(迪杰斯特拉)算法讲解及代码实现

            迪杰斯特拉算法是一种广义的贪心算法,求出局部最优解,再去求全局最优解 举例图:(起始点为1) 辅助数组: s:记录了目标顶点到其他顶点的最短路径是否求得(求得为1,否则为0) p:目标顶点到其他顶点的最短路径的前驱节点 (如,求得1-7-5的最短路径,那

    2024年02月11日
    浏览(38)
  • MATLAB轻松绘制地图路线——Dijkstra(迪杰斯特拉)算法最短路径规划

    利用MATLAB绘制地图需要三个基本数据: 节点 节点坐标 节点间相通的路线 以11B交通巡警平台调度问题中的A区数据为例: (数据及工程文件下载链接见文末) Demo1: 可通过已知节点的坐标,计算出各节点之间的距离,有Matlab基础的同学可以尝试Demo2, 也可通过Excel自行实现;

    2023年04月21日
    浏览(49)
  • 数据结构与算法 —— 最短路径Dijkstra算法(迪杰斯特拉)详细图解以及python实现

    目录 前言 1. 介绍 2. 加权图 2.1 概念 3. 最短路径 -- Dijkstra 算法 3.1 历史 3.2 Dijkstra 算法的基本思路 3.3 Dijkstra 算法图解 4.  python中dijkstra算法的实现 5. 总结  前两章我们讲到了关于图的基本知识,和广度/深度优先搜索。 本章,我们将介绍 加权图 和 最短路径 的相关知识。 最

    2024年02月12日
    浏览(52)
  • 迪杰斯特拉(Dijkstra's )算法——解决带权有向无向图最短路径

    迪杰斯特拉算法(Dijkstra\\\'s Algorithm),又称为狄克斯特拉算法,是一种用于解决带权重有向图或无向图最短路径问题的算法。该算法由荷兰计算机科学家艾兹赫尔·狄克斯特拉在1956年发明,是一种广泛应用于网络路由和其他领域的算法。 在 2001 年的一次采访中,Dijkstra 博士透露

    2024年02月03日
    浏览(48)
  • 使用omp并行技术加速最短路径算法-迪杰斯特拉(Dijkstra)算法(记录最短路径和距离)

    原理: Dijkstra算法是解决**单源最短路径**问题的**贪心算法** 它先求出长度最短的一条路径,再参照该最短路径求出长度次短的一条路径     直到求出从源点到其他各个顶点的最短路径。 首先假定源点为u,顶点集合V被划分为两部分:集合 S 和 V-S。 初始时S中仅含有源点u,

    2024年02月10日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包