首页 > 编程语言 >Dijkstra算法

Dijkstra算法

时间:2022-10-05 10:45:41浏览次数:78  
标签:算法 dist int Dijkstra 距离 flag dijkstra ver

求是单源最短路径,即给定一个源点,求其到其他顶点的最短路径。Dijkstra算法就是解决它的,而其前提条件是图中每条边的权重不为负值。

朴素版用于处理稠密图,使用邻接矩阵存储图;优化版用于处理稀疏图,使用邻接表存储图。

朴素版

题目链接:Dijkstra求最短路 I

思路

​ 集合S为已经确定最短路径的点集。

  1. 初始化距离:一号结点的距离为零,其他结点的距离设为无穷大。
  2. 循环n次(n为顶点数),每一次将集合S之外距离最短的点T(dist值最小)加入到S中去(这里的距离最短指的是距离1号点最近。点T的路径一定最短,基于贪心)。然后用点T更新T的邻接点的距离。

C++

#include <iostream>
#include <cstring>

using namespace std;

const int N = 510;
int g[N][N];
int dist[N];
bool flag[N];
int n, m;

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);  // 初始化所有离源点的距离为无穷大
    dist[1] = 0;  // 源点离自身的距离为0
    
    for (int i = 1; i <= n; i++)
    {
        int t = -1;
        // 找到未确定到源点距离的点中dist值最小的那个点
        for (int j = 1; j <= n; j++)
            if (!flag[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
                
        flag[t] = true;  // 接下来确定这个点到源点的距离
        
        // 更新其他未确定的并于点t的连通的点的dist值
        for (int j = 1; j <= n; j++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }
    
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];  // 如果汇点(终点)的值不为无穷大,则说明其于源点连通,返回其dist值
}

int main() 
{
    cin.tie(0);
    cin >> n >> m;
    
    memset(g, 0x3f, sizeof g);
    while (m --)
    {
        int x, y, z;
        cin >> x >> y >> z;
        g[x][y] = min(g[x][y], z);  // 重边和自环可以通过取最小权重来解决
    }
    
    cout << dijkstra() << endl;
    
    return 0;
}

Python

n, m = map(int, input().split())
maxdist = float("inf")
g = [[maxdist] * (n + 1) for _ in range(n + 1)]
flag = [False] * (n + 1)
dist = [maxdist] * (n + 1)

for _ in range(m):
    x, y, z = map(int, input().split())
    g[x][y] = min(g[x][y], z)


def dijkstra():
    dist[1] = 0
    for i in range(1, n + 1):
        t = -1
        for j in range(1, n + 1):
            if not flag[j] and (t == -1 or dist[t] > dist[j]):
                t = j
                
        flag[t] = True
        
        for j in range(1, n + 1):
            dist[j] = min(dist[j], dist[t] + g[t][j])
    
    return dist[n] if dist[n] < maxdist else -1
    

print(dijkstra())

优化版

题目链接:Dijkstra求最短路 II

思路

​ 堆优化版的dijkstra是对朴素版dijkstra进行了优化,在朴素版dijkstra中时间复杂度最高的寻找距离最短的点O(n^2)可以使用最小堆优化为O(logn)。

  1. 一号点的距离初始化为零,其他点初始化成无穷大。
  2. 将一号点放入堆中。
  3. 不断循环,直到堆空。每一次循环中执行的操作为:
    弹出堆顶(与朴素版diijkstra找到S外距离最短的点相同,并标记该点的最短路径已经确定)。
    用该点更新临界点的距离,若更新成功就加入到堆中。

C++

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

using namespace std;

typedef pair<int, int> PII;

const int N = 150010;
int n, m;
int idx = 0;
int h[N], ne[N], val[N], w[N];
int dist[N];
bool flag[N];

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

int dijkstra2()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    priority_queue<PII, vector<PII>, greater<PII>> pq;
    pq.push({ 0, 1 });
    
    while (pq.size())
    {
        PII k = pq.top();
        pq.pop();
        
        int ver = k.second, distance = k.first;
        if (flag[ver]) continue;
        flag[ver] = true;
        
        // 稀疏图使用邻接表的方式,在这里遍历时的时间复杂度要更低
        // 对于当前选中的顶点ver,遍历与该点连通的顶点
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = val[i];  // i只是顶点的一个编号,而val[i]代表的才是其顶点
            // 更新与顶点ver连通的顶点的dist值
            if (dist[j] > distance + w[i])
            {
                dist[j] = distance + w[i];
                pq.push({ dist[j], j });  // 加入优先队列
            }
        }
    }
    
    return dist[n] == 0x3f3f3f3f ? -1 : dist[n];
}

int main() 
{
    memset(h, -1, sizeof h);
    cin >> n >> m;
    
    while (m--)
    {
        int x, y, z;
        cin >> x >> y >> z;
        add(x, y, z);  // 对于用邻接表存储的图,构建图时可以不用特殊处理重边和自环
    }
    
    cout << dijkstra2() << endl;

    return 0;
}

标签:算法,dist,int,Dijkstra,距离,flag,dijkstra,ver
From: https://www.cnblogs.com/liuyxcc/p/16755181.html

相关文章

  • 一文图解单目相机标定算法
    有一天,蟹老板找底下的员工川建国同学:等蟹老板走后,然后转头问旁边的学霸李雷同学:李雷同学整理了下情绪:有人反映哦,有时候我们发出来的技术贴太硬了,不方便去理解,于是,就有了上面......
  • 招聘|20~40K|高级算法工程师&SLAM算法高级工程师
    公司介绍:北京中科慧眼科技有限公司国家高新技术企业,中关村前沿科技企业国内80%以上自动驾驶项目双目感知技术提供商百度Apollo自动驾驶生态投资的国内唯一一家智能视觉公司......
  • 老生常谈React的diff算法原理-面试版
    第一次发文章notonly(虽然)版式可能有点烂butalso(但是)最后赋有手稿研究finally看完他你有收获diff算法:对于update的组件,他会将当前组件与该组件在上次更新是对应的......
  • 求多项式和 求序列最大值 的奇怪算法代码
         递归 ......
  • SPAFA 和Dijkstra的区别
    SPAFA和Dijkstra的区别Dijkstra算法和SPFA算法都可以用于求单源最短路,前者可以用小根堆进行优化,后者用就是用队列优化过的Bell-manFord,下面说一说这两者的区别:Dijkstra......
  • java算法——自建对数器
    用于验证所写算法是否正确,与java自带的函数方法进行比较,例如写一个排序算法,验证排序算法是否正确,采用Arrays.sort(arr)的方式,与自己所写的算法进行比对,经过多轮(比较大的一......
  • java 算法——异或运算练习
    packageclass01;//在一个数组中已知数组中只有一种数出现了奇数次,其他的是所有数都出现了偶数次怎么找到出现奇数次的数对所有数字取异或最终结果就是奇数次那个数......
  • java算法——二分法及其拓展
    题目描述:在一个无序数组中,任何相邻的两个数一定不相等,求规定范围内它局部最小的那个数要求:计算的过程时间复杂度小于O(N)思路:由于所有相邻的两个数一定不相等,若一个数的左......
  • 蔚来招聘|多传感器联合标定算法工程师
    3D视觉工坊致力于推荐最棒的工作机会,精准地为其找到最佳求职者,做连接优质企业和优质人才的桥梁。团队介绍我们是谁?蔚来是一家全球化的智能电动汽车公司,于2014年11月成立。蔚......
  • XYZ Robotics招聘|机器人3D视觉及成像、深度学习、机器人系统算法工程师等岗位
      机器人技术正在改变世界!公司介绍:星猿哲科技(XYZRobotics)致力赋予机器人全自主感知与操作的能力,变革生产方式,解放人类双手。成立于2018年,我们凭借全球领先的3D视觉、机......