C++实现Dijkstra算法

描述:
网上已经有很多对于该算法的详尽描述了,本文不做赘述。
本文的目的是提供给大家一个带有清晰注释的使用C++实现Dijkstra算法的代码。

源代码:

//
//  main.cpp
//  DijkstraAlgorithm
//
//  Created by 胡昱 on 2021/12/21.
//

#include <iostream>
#include <cstring>
#include <limits.h>
using namespace std;

// 定义相关参数
const int MAX_N = 500;           // 最大顶点数
int graph[MAX_N + 1][MAX_N + 1];        // 以二维数组graph表示图,注意点的编号是从1开始的
int dis[MAX_N + 1];                     // 从起点s到其他点的距离数组dis
bool mark[MAX_N + 1];                   // 记录某点是否已被访问的数组
int n, E, s, t;                         // 顶点数n、边数E、起点s以及终点t

// 主函数
int main(int argc, const char * argv[]) {
    // 共T组测试用例
    int T;
    cin >> T;
    while((T--) > 0) {
        // 初始化,注意memset(..., 127, ...)是将数组中的所有元素全为2139062143,即无穷大
        memset(graph, 127, sizeof(graph));
        memset(dis, 127, sizeof(dis));
        memset(mark, false, sizeof(mark));
        
        // 输入顶点数n、边数E、起点s以及终点t
        cin >> n >> E >> s >> t;
        
        // 顶点u到顶点v之间无向边长度w
        // 因为可能有重边,所以需要取最小者
        // 虽然是无向图,但是我们改成有向图来处理
        for(int ei = 0; ei < E; ++ei) {
            int u, v, w;
            cin >> u >> v >> w;
            graph[u][v] = min(graph[u][v], w);
            graph[v][u] = min(graph[v][u], w);
        }
        
        // 开始Dijkstra算法
        
        // 起点到起点的距离应该为0
        dis[s] = 0;
        
        // 外层大循环保证所有点都会被访问到
        // 在输入的时候并没有更新dis数组,因为很明显第一个被访问的就是起点s(距离dis[s]为0)
        for(int ni = 1; ni <= n; ++ni) {
            
            // 记录当前访问的点的变量
            int currentDis = INT_MAX;
            int currentVex;
            
            // 在未被访问过的点中寻找当前需要访问的点
            // 也就是未被访问过的、和起点距离最短的点
            for(int cvi = 1; cvi <= n; ++cvi) {
                if((!mark[cvi]) && (dis[cvi] < currentDis)) {
                    currentDis = dis[cvi];
                    currentVex = cvi;
                }
            }
             
            // 将该点设置成已访问状态
            mark[currentVex] = true;
            
            // 更新所有和当前点连接的点的距离
            /*
             问:这边为什么不用考虑更新已经访问过的点的距离呢?
             答:因为已访问的点到起点s的距离一定小于当前点到起点s的距离,
                所以从起点s到当前点再到已访问的点的距离一定大于从起点s到已访问的点的距离
             */
            for(int i = 1; i <= n; ++i) {
                // 如果点i未被访问、且从起点s到当前点currentVex再到点i的距离小于现有的从起点s到点i的距离的话,则更新
                if((!mark[i]) && (dis[currentVex] + graph[currentVex][i] < dis[i])) {
                    dis[i] = dis[currentVex] + graph[currentVex][i];
                }
            }
        }
        
        // Dijkstra算法结束,从代码中的两层for循环可以很明显看出时间复杂度为O(n^2)
        
        // 输出结果(如果从起点s无法到达终点t则输出-1)
        if(dis[t] == INT_MAX) {
            cout << -1 << endl;
        }
        else {
            cout << dis[t] << endl;
        }
    }
    return 0;
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值