迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少

首先来一段百度百科压压惊。。。

迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

让我来翻译一下:
Dijkstra可以求出一个点到一个图中其他所有节点的最短路径,故也称对于单源最短路径的一种解法

算法实现步骤:

a.初始时,只包括源点,即S = {v},v的距离为0。U包含除v以外的其他顶点,即:U ={其余顶点},若v与U中顶点u有边,则(u,v)为正常权值,若u不是v的出边邻接点,则(u,v)权值 ∞;
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。

c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。

d.重复步骤b和c直到所有顶点都包含在S中。

动画模拟:

普通版Dijkstra代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int map[100][100];
int vis[100];
int way[100];
int n,e,w,s;
int main(){
    freopen("dij.in","r",stdin);
    freopen("dij.out","w",stdout);
       int i,j,x,y,z,w,mi=20000;
       scanf("%d%d",&n,&e);
       for(i=1;i<=e;i++)
       {
             scanf("%d%d%d",&x,&y,&z);
             map[x][y]=z;
             map[y][x]=z;
       }
       memset(way,127,sizeof(way));
       scanf("%d",&s);
       way[s]=0;
       for(i=1;i<n;i++)
       {
              for(j=1;j<=n;j++)
                  if(way[j]<mi&&vis[j]==0)
                  {
                        mi=way[j];
                        w=j;
                  }
              vis[w]=1;
              for(j=1;j<=n;j++)
                  if(map[w][j]!=0&&vis[j]==0&&way[j]>way[w]+map[w][j])
                     way[j]=way[w]+map[w][j];
       }
       for(i=1;i<=n;i++)
           printf("%d ",way[i]);
       return 0;
}

那现在让我们分析一下复杂度,很明显高达O(N*N),那当做一些题时不论内存还是时间都会爆,那就急需我们做一些优化了

Dijkstra的堆优化:

依旧是迪杰斯特拉算法的思想,寻找当前距离最小的点,然后将它标记为已经确定的点,用它来更新各个没被确定的点。

emmmm我们选择优先队列来确定每一个最小距离的点

例题:

代码如下:

#include<bits/stdc++.h>
using namespace std;
struct SYM{
    int to,next,w;
}edge[500010];
struct LKJ{
    int v,c;
    bool operator <(const LKJ &a)const {
        return c>a.c;
    }
};
priority_queue<LKJ,vector<LKJ> > q;
int head[101000],vis[101000],tot,dis[101000],n,m,k;
void add(int x,int y,int w){
    edge[++tot].to=y;
    edge[tot].w=w;
    edge[tot].next=head[x];
    head[x]=tot;
}
void dij(int s){
     dis[s]=0;
     LKJ hh;hh.v=s;hh.c=0;
     q.push(hh);
     while(!q.empty()){
         LKJ tmp=q.top();q.pop();
         int x=tmp.v;
        if(vis[x]) continue;vis[x]=1;
         for(int i=head[x];i;i=edge[i].next)
             if(!vis[edge[i].to]&&dis[edge[i].to]>dis[x]+edge[i].w){
                 dis[edge[i].to]=dis[x]+edge[i].w;
                 hh.v=edge[i].to;hh.c=dis[edge[i].to];
                 q.push(hh);
             }
    }
}
int main(){
    memset(dis,127,sizeof(dis));
    int x,y,w;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);
    }
    dij(k);
    for(int i=1;i<=n;i++){
        if(dis[i]==2139062143) printf("2147483647 ");
        else printf("%d ",dis[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/tonyshen/p/11698469.html

时间: 2024-10-28 20:33:02

迪杰斯特拉算法(Dijkstra) (基础dij+堆优化) BY:优少的相关文章

C# 迪杰斯特拉算法 Dijkstra

什么也不想说,现在直接上封装的方法: using System; using System.Collections.Concurrent; using System.Collections.Generic; namespace 算法 { /// <summary> /// Dijkstra /// 迪杰斯特拉算法 /// </summary> public class Dijkstra : ICloneable { /// <summary>节点集合</summa

算法--迪杰斯特拉算法 Dijkstra

https: //www.bilibili.com/video/av47427754?from=search&seid=10869921304007190819 import java.util.*; public class djstl { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); // n个点 m条边 x为开始点 如1到6 1为开始点

十大基础实用算法之迪杰斯特拉算法、最小生成树和搜索算法

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离). 初始时,S中只有起点s:U中是除s之外的顶点,并且U中顶点的路径是"起点s

普里姆算法,克鲁斯卡尔算法,迪杰斯特拉算法,弗洛里德算法

做数据结构的课程设计顺便总结一下这四大算法,本人小白学生一枚, 如果总结的有什么错误,希望能够告知指正 普里姆算法如图所示prim 找出最短的边,再以这条边构成的整体去寻找与之相邻的边,直至连接所有顶点,生成最小生成树,时间复杂度为O(n2) 克鲁斯卡尔算法如图所示kruskal 克鲁斯卡尔算法,假设连通网N=(N,{E}),则令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),图中每个顶点 自成一个连通分量.在E中选择代价最小的边,若该边依附的定顶点落在T中不同的连通分量上,

最短路径之迪杰斯特拉(Dijkstra)算法

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法.本文先来讲第一种,从某个源点到其余各顶点的最短路径问题. 这是一个按路径长度递增的次序产生最短路径的算法,它的大致思路是这样的. 初始时,S中仅含有源.设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度.D

最短路径 - 迪杰斯特拉(Dijkstra)算法

对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法.本文先来讲第一种,从某个源点到其余各顶点的最短路径问题. 这是一个按路径长度递增的次序产生最短路径的算法,它的大致思路是这样的. 比如说要求图7-7-3中顶点v0到v1的最短路径,显然就是1.由于顶点v1还与v2,v3,v4连线,所以此时我们同时求得了v0->v1->v2 = 1+3 =

最短路径算法——迪杰斯特拉算法(Dijkstra)

图结构中应用的最多的就是最短路径的查找了,关于最短路径查找的算法主要有两种:迪杰斯特拉算法(Dijkstra)和Floyd算法. 其中迪杰斯特拉算法(Dijkstra)实现如下: 原理就是不断寻找当前的最优解: void main() { int V[Max][Max]={0,8,32,Infinity,Infinity, 12,0,16,15,Infinity, Infinity,29,0,Infinity,13, Infinity,21,Infinity,0,7, Infinity,Infi

迪杰斯特拉(dijkstra)算法的简要理解和c语言实现(源码)

迪杰斯特拉(dijkstra)算法:求最短路径的算法,数据结构课程中学习的内容. 1 . 理解 算法思想::设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将 加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中.在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v

[小明学算法]4.Dijkstra(迪杰斯特拉)算法

1.定义概念 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.值得注意的是,该算法要求图中不存在负权边. 2.基本思想 设置顶点集合S,初始时,S中仅含有起始点,把从起始点到u且中间只经过S中顶点的路称为从起始点到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径的长度.Dijkstra算法每次从S外取出对应dist值最小的节点u,将其添加到S中,并对所有与u点直接相连