【基础学习】Dijkstra算法

为手撕准备,多多讨论

原理

Dijkstra算法是种贪心算法,图搜索算法,每次寻找的是距离起始点最近的点,直到所有点都找完,该种方法能确保找到最优路径,但是时间长些

c++代码

假设输入格式为:共m个节点,n条连接关系,连接关系表示为"节点编号 代价权重 父连接节点编号"字符串,终点节点编号。其中, 节点0为起始节点,例如 1,0,1 表示节点0到节点1的代价权重为1
输出: 从初始起点到任意点的最小代价,初始点到终点的路径

// Dijkstra algorithm implementation
// 手撕 简单版本
// 2024-4-24
// Dijkstra algorithm implementation
// 手撕 简单版本
// 2024-4-24

#include <iostream>
#include <vector>
#include <unordered_set>
#include <string>

using namespace std;

vector<int> Dijkstra(vector<vector<int>>& graph, int start, vector<int>& dist){
    int m = graph.size()-1;
    unordered_set<int> visited;
    visited.insert(start);
    vector<int> path(m, start); // 存储父节点
    
    while(visited.size() < m){
        // 更新其他节点的最短路径
        for(int i=0;i<m;i++){
            if(visited.find(i) == visited.end() && graph[start][i] + dist[start] <= dist[i] && graph[start][i] != INT32_MAX){
                dist[i] = dist[start] + graph[start][i];
                cout << "update dist[" << i << "] = " << dist[i] << endl;
                path[i] = start; 
            }
        }
        // 可走路径中选取当前最短路径节点
        int min_dist = INT32_MAX;
        int min_node;
        for(int i=0;i<m;i++){
            if(visited.find(i) == visited.end() && dist[i] <= min_dist){
                min_dist = dist[i];
                min_node = i;
            }
        }
        visited.insert(min_node);
        start = min_node;
    }
    return path;
}   

int main(){
    // 假设输入格式为 共m个节点,n条连接关系,连接关系表示为"节点编号 代价权重 父连接节点编号"字符串,终点节点编号
    // 节点0为起始节点
    // 例如 1,0,1 表示节点0到节点1的代价权重为1
    int n, m;
    cin >> m >> n;
    vector<vector<int>> graph(m+1, vector<int>(m+1, INT32_MAX));
    vector<int> dist(n, INT32_MAX); // 从0到每个节点代价
    for(int i=0;i<n;i++){
        string s;
        cin >> s;
        int u, v, w;
        u = stoi(s.substr(0, s.find(',')));
        s = s.substr(s.find(',')+1);
        w = stoi(s.substr(0, s.find(',')));
        s = s.substr(s.find(',')+1);
        v = stoi(s.substr(s.find(',')+1));
        graph[v][u] = w;
    }
    int ed;
    cin >> ed;
    dist[0] = 0;
    graph[0][0] = 0; // 初始化起始节点

    // 查看graph
    for(int i=0;i<m;i++){
        for(int j=0;j<m;j++){
            cout << graph[i][j] << " ";
        }
        cout << endl;
    }

    vector<int> path = Dijkstra(graph, 0, dist);

    // 输出最短路径代价
    for(int i=0;i<m;i++){
        cout << "minimum cost from 0 to " << i << ": " << dist[i] << endl;
    }
    cout << "path from 0 to " << ed << endl;

    // 输出终点节点编号的最短路径 
    while(ed != 0){
        cout << ed << " ";
        ed = path[ed];
    }
    cout << 0 << endl;
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值