详解单源最短路径问题-迪杰斯特拉算法(Dijsktra)

本文详细介绍了迪杰斯特拉算法,这是一种用于计算图中单源最短路径的典型算法。内容涵盖算法定义、思想、具体实现过程以及两种模板题的解题思路,包括朴素的Dijkstra算法和堆优化版。
摘要由CSDN通过智能技术生成

Dijsktra算法的定义

  Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径(单源最短路径)。

算法思想

  设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。
  在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

具体的实现过程

  假设a为起始点,a到a的最短路径是0,a到b的最短路径是1,a到c的最短路径是3,a到d的最短路径是8,a到e的最短路径是11。

用Dijkstra实现单源最短路:
  Dijkstra的思想是先初始化这样一张表(除了a之外,a到其他点的距离都是正无穷):

  在表中选择一个路径最短的点a,从a出发,a到自己的距离是0,它往外有三条边,更新a到b、c、d的最短距离,a这一点已经考察完了,以后a点不会被选到,此时表更新为:

  在这张表中再选一个最短距离(a到b),选出点b,它有两条边指向c和e,从a出发,若经过b到达c,则现在的距离是3,比之前从a直接到c大,所以更新最短距离,以后b点不会被选到,此时表更新为:

  在这张表中再选一个最短距离(a到c),选出c点,c往外有两条边,此时到e的距离为23(经过c),比原来的51小,更新最短距离;此时到d的距离为8(经过c),比原来的10小,更新最短距离,以后c点不会被选到,此时表更新为:

  在这张表中再选一个最短距离(a到d),选出d点,d往e有一条边,此时到e的距离为11(经过d),更新最短距离,此时表更新为:

  在这张表中再选一个最短距离(a到e),它往外没有边,结束。所以这个表就是最后的结果,Dijkstra只有一个要求:不要出现权值加起来是负数的环即可。
  权值是负数的话最短距离会变成负无穷(不停地转,最短距离会不断减小),比如:

模板题(一)

  下面介绍一道模板题来实现这种基本的算法思想:
POJ - 2387 Til the Cows Come Home
  大概意思:输入总共有n个点的无向图的边数和权值,求出从起点1到点n的最短距离。

朴素的dijkstra算法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
const int N = 1005;
int n, m, g[N][N], dist[N], st[N];	//g数组是记录从某点到某点的权值,dist数组表示任意点到点1的最短距离,st数组是标记已求出最短路径的顶点
int read(){
   
    int x, f = 1;
    char ch;
    while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
    x = ch - '0';
    while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
    return x * f;
}
int dijkstra(){
   
    int i, j, t;
    memset(dist, 0x3f, sizeof(dist)); //把所有点到起点最短距离初始化为正无穷
    dist[1] = 0;	//起点到起点的最短距离为0
    for(i = 1; i <= n; i++){
   	//每轮循环得到一个确定最短路径的顶点
        t = -1;	//t是个临时变量,为了确定某个点到起点的最短距离,并且把其放入已求出最短路径的顶点的集合里面
        for(j = 1; j <= n; j++){
   
            if(!st[j] && (t == -
  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值