为手撕准备,多多讨论
原理
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;
}