给定一个有向图 G,图中的边的权重值非负,要求找出从出发点 s 到图中其它各个节点的 最短路径。以上问题可以用 Dijkstra 算法求解,请描述其过程,并给出时间复杂度及C++代码实现
时间: 2024-05-08 17:15:16 浏览: 120
Dijkstra 算法的过程:
1. 初始化:将起点 s 的距离设置为 0,将其它节点的距离设置为无穷大(表示暂时不可达),将所有节点的状态设置为“未确定最短路径”。
2. 确定最短路径:从未确定最短路径的节点中选择距离起点 s 最近的节点 v,将其状态设置为“已确定最短路径”,并更新从起点 s 到其它节点的距离:
对于节点 v 的所有出边 (v, w),如果从起点 s 到节点 v 的距离加上边权值比起点 s 到节点 w 的当前距离更短,则更新节点 w 的距离为新的距离。
3. 重复步骤 2 直到所有节点的状态都为“已确定最短路径”。
时间复杂度为 O(E + VlogV),其中 E 为边数,V 为节点数,使用堆优化可以降低时间复杂度。
代码实现:
```
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f; // 无穷大
struct Edge {
int to, weight;
Edge(int t, int w) : to(t), weight(w) {}
};
typedef vector<vector<Edge>> Graph; // 邻接表表示图
void dijkstra(const Graph& G, int s, vector<int>& dist) {
int n = G.size();
dist.resize(n, INF); // 初始化距离为无穷大
dist[s] = 0; // 起点距离为 0
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 小根堆
pq.push(make_pair(0, s)); // 起点入队
while (!pq.empty()) {
int d = pq.top().first; // 当前最短距离
int v = pq.top().second; // 当前节点
pq.pop();
if (dist[v] < d) continue; // 如果已经确定最短路径,则直接跳过
for (const Edge& e : G[v]) { // 遍历当前节点的出边
if (dist[e.to] > dist[v] + e.weight) { // 如果经当前节点到达 e.to 更短
dist[e.to] = dist[v] + e.weight; // 更新距离
pq.push(make_pair(dist[e.to], e.to)); // e.to 入队
}
}
}
}
int main() {
int n, m, s;
cin >> n >> m >> s;
Graph G(n);
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
G[u].emplace_back(v, w); // 添加边
}
vector<int> dist;
dijkstra(G, s, dist);
for (int i = 0; i < n; i++) {
if (dist[i] < INF) cout << dist[i] << endl;
else cout << "INF" << endl;
}
return 0;
}
```
阅读全文