首页 > 编程语言 >单源正权最短路径——Dijkstra算法

单源正权最短路径——Dijkstra算法

时间:2024-02-02 21:00:12浏览次数:24  
标签:算法 结点 源点 cur 正权 路径 单源 Dijkstra

目录

问题引入

给出n点m边,其中边的权值皆为非负数,要求快速给出一个点到其余点的最短距离

思路一览

  • dfs遍历维护最短距离
  • floyd算法算全源最短,但是这玩意时间复杂度O(n3),最多也就1000个点左右
  • 主角Dijkstra算法

算法原理

主要是以源点为根节点逐步构建一棵最短路径树,也就是从未加入最短路径树的结点中选择最短的与树相连的边加入最短路径树,总的来说还是一种贪心的思想,Dijkstra算法生效的条件或者有两条,一是边权要全部都是正边权,不能存在负边权,不然贪心就不成立,二是源点和某一结点的路径上的点一定是最短路径,假设存在源点u,终点v存在一条最短路径和中继结点mid,假设存在一条由u到mid的更短路径,那么该uv的最短路径便不成立,因为u可以从另外那条到mid的更短路径到达mid结点,再到达v结点(该条证明的前提是第一个条件)。
根据上面两个原理就可以这样操作得到源点到其他结点的最短距离:首先将与源点直接相连的结点加入集合w中,然后从中选择不在树上的最短的边,接着将加入结点的相连边加入集合,继续选,直到集合为空,在选择过程中要及时更新已经在树上的结点。分析时间复杂度就是发现每次在集合中找最短边的过程最耗时,所以选择用集合或者小根堆优化程序。

code

int n, m, k, vis[N], dis[N];
vector<pii> e[N];
priority_queue<pii, vector<pii>, greater<pii>> w;
void Dijkstra(int cur) {
    memset(dis, 127, sizeof dis);
    //初始条件
    w.push({0, cur});
    while(!w.empty()) {
        while(!w.empty() && vis[w.top().second]) w.pop();
        if(w.empty()) break;
        //其实这里还可以加入一个跳出条件,参照prim算法构建最小生成树
        //加一个最短路径树上的结点值cnt,当cnt==n时跳出
        int curDis = w.top().first, cur = w.top().second;
        vis[cur] = 1, dis[cur] = curDis;
        for(auto z:e[cur]) {
            int nxt = z.first, addDis = z.second;
            if(!vis[nxt]) w.push({addDis+curDis, nxt});
        }
    }
}

标签:算法,结点,源点,cur,正权,路径,单源,Dijkstra
From: https://www.cnblogs.com/notalking569/p/18003990

相关文章

  • 单源最短路径算法之bellman-ford
    单源最短路径算法之\(bellman-ford\)以边为研究对象单起点多终允许有负边权\(bellman-ford\)的工作原理假设\(n\)个点\(m\)条有向边的图,求\(s\)为起点的最短路条以\(s\)出发的最短路,最多包含\(n\)个点,\(n-1\)条边对于一条边\((x,y,w)\),\(y\)可能被\(x\)......
  • 洛谷题解-P3003 [USACO10DEC] Apple Delivery S (dijkstra)
    题目描述Bessiehastwocrispredapplestodelivertotwoofherfriendsintheherd.Ofcourse,shetravelstheC(1<=C<=200,000)cowpathswhicharearrangedastheusualgraphwhichconnectsP(1<=P<=100,000)pasturesconvenientlynumb......
  • Dijkstra算法
    \(Dijkstra\algorithm\)\(Principle\)以点为研究对象的贪心策略,和\(Prim\)类似。\(Implementation\step\)将起点标记;找条连接被标记的点集合中一点和没有被标记的点集合中一点最短的边;将该边连接的没有被标记的点加入被标记的点;将该新加入的被标记的点和它的所有邻接点......
  • dijkstra算法(单源最短路径)
    单源最短路径是求解给定一个起点到其他所有的点的最短距离。适用的范围:有向图、边的权值没有负数洛谷测试链接代码实现#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<time.h>#include<stdboo......
  • 图的最短路-Dijkstra 详解
    Dijkstra  概念注意一下,Dijkstra不适用于有负边权的图   就是刚开始一些点(集合B),把排序的结果放入集合A,先确定起点0,然后找集合B里面的最小值,这样才可以确定你修改的这个点的最短路在目前是最优解(后期可能改动),因为集合A的都是确定好了的最短路,所以集合A的数不做修......
  • Dijkstra基本内容
    众所周知,Dijkstra算法是一个十分有效且常用的算法.既然说了,有效且常用那我们就有课学习的必要了呀!话不多说,开始讲解.概念1.是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。Dijkstra算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点......
  • C++U6-02-最短路算法1-dijkstra迪杰斯特拉最短路径
    学习目标 最短路径的基本概念  练习1 最短路的定义 本节课迪杰斯特拉dijkstra最短路算法 算法流程:以下是Dijkstra最短路径算法的逐步计算松弛的过程:初始化起始节点的距离为0,其他节点的距离为无穷大。选择当前距离最小且未被访问的节点作为当前节点。......
  • Bellman-Ford算法实现带有负权边的单源最短路
    Bellman-Ford算法对于Dijkstra算法,不妨给出这样一个例子graphLRA((A))-->|1|C((C))A-->|2|D((D))D-->|-4|C根据Dijkstra算法的流程,选取A为源点。更新与A邻接的顶点,有C和D。选取已更新顶点中距离A的最小值,显然选择边权为1的边所连接的顶点C,并将C收入最短路集合S中,此......
  • G. Bicycles 分层图单源最短路
    题目链接简单描述一下题意:给定n个点,m条带权无向边,每个点i有一辆速度系数为Si的自行车。每经过一个点即可拥有该点的自行车,在任意两点之间路过的消耗为:已经拥有的某辆自行车的速度Si*边权Wi,求从1号点到n号点的最小消耗。思路:因为需要求的是最小的总消耗,所以在某个点出发时,我......
  • Dijkstra实现单源最短路
    Dijkstra算法求单源最短路Dijkstra算法应用于求一个给定图的单个源点到其他各顶点的最短路。其中应用Dijkstra算法的图应满足如下条件图中没有负权边有向或者无向图都可以图中若有自环或者重边也可以(需要自己先筛选一下)Dijkstra算法的核心就是从源点开始对各个顶点进行......