(算法基础)朴素版的Dijkstra算法

适用情景

  1. 在最短路问题当中的单源最短路(一号点到其他所有点之间的距离)的只有正权边的情况,且朴素版适用于稠密图(n^2 ~ m)


时间复杂度

  1. O(N^2)


算法解释(朴素版的Dijkstra)

  1. 首先是关于这个图的存储,图的话主要是分为稠密图与稀疏图。稠密图就是说n的平方与m是一个量级的,对于稠密图的话,用邻接矩阵来存;稀疏图的话是n与m为一个量级的,对与稀疏图的话,就用邻接表来存。在这边我先举一个用邻接矩阵存图为例子吧。

int g[N][N];
  1. 然后这个邻接矩阵等会儿我是要把具体的边的信息放进去的,所以在一开始有必要进行一些预处理初始化,在最短路问题当中有两类特殊情况:这就是重边,一个就是自环,由于当下背景是最短路,对于重边而言的话,只需要取小的就可以;然后对于自环而言的话,不能是负环(不然最短路就变成负无穷了),然后对于正环而言的话,在最短路里相当于没有。这些得知道。初始化

memset(h,0x3f,sizeof(h));
  1. 然后还需要开两个数组,一个数组就是用来记录一下该点是不是已经确定了最短路距离,还有一个数组用来记录一下每点到一号点之间的最短路距离是多少,一开始的话每点初始化为正无穷(当然,一号点除外,它到他自己本身的距离就是0

int st[N];
int dist[N];
memset(dist,0x3f3f3f3f,sizeof(dist));
dist[1]=0;
  1. 然后往邻接矩阵里面输入每一条边的有关信息.

while(m--)
{
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
    g[a][b]=MIN(g[a][b],c);
}
  1. 然后就进入了迪杰斯特拉算法的精髓:首先要去找到这么一个点1. 还没有被正式确认下来最短路距离,2. 到1号点的距离比其他与他一样的同胞(还没有被正式确认最短路距离)到一号点的距离都要短(因此逃不开还要遍历一遍所有点)。先把这个点去找到,这个点找到之后,去遍历一下这个点所能连接到的其他点,看一看能不能更新那些点的最短路距离。遍历一圈完成之后,这个点的最短路距离也就正式被确定下来然后依次往复,不断循环。显而易见,每一次循环确定下来一个点的最短路距离,既然有n个点,那么就需要n次循环

for (int i=0;i
  1. 然后由于迪杰斯特拉算法的要求,就是说所有的边都必须是正权边,因此如果说从一号点走不到n号点的话,那么n号点的距离dist应该还是保持初始化的那个值0x3f3f3f3f,在当前情形是不存在负权边,这个初始化的正无穷大值不会被略微更新小

if (dist[n]==0x3f3f3f3f)
{
    printf("%d\n",-1);
}
else
{
    printf("%d\n",dist[n]);
}

例题

来源:AcWing

849. Dijkstra求最短路 I - AcWing题库

(算法基础)朴素版的Dijkstra算法_第1张图片
#include 
#include 
#define N 510
#define MIN(a,b) ((a)<(b)?(a):(b))
int g[N][N];
int st[N];
int dist[N];
int main()
{
    memset(dist,0x3f3f3f3f,sizeof(dist));
    dist[1]=0;
    int n,m;
    scanf("%d %d",&n,&m);
    memset(h,0x3f,sizeof(h));
    while(m--)
    {
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        g[a][b]=MIN(g[a][b],c);
    }
    for (int i=0;i

你可能感兴趣的:((针对ACM)算法,算法)