Dijstra
Dijkstra 算法简介与 C++ 实现模板
一、算法概述
Dijkstra 算法是一种用于解决单源最短路径问题的经典算法。给定一个带权有向图或无向图,算法可以求出从源点到图中每个顶点的最短路径长度。其核心思想是贪心策略:每次选择当前距离源点最近的未处理节点,并更新其邻居的最短路径。
特点
- 适用于非负权重图(边权必须 ≥ 0)。
- 可以用于有向图或无向图。
- 时间复杂度:
- 使用数组实现:(O(V^2))
- 使用优先队列(最小堆)实现:(O(E \log V)),其中 (V) 为顶点数,(E) 为边数。
二、算法原理
- 初始化源点
dist[source] = 0,其他顶点距离为无穷大。 - 将所有顶点加入未处理集合(或使用优先队列维护)。
- 每次从集合中选取距离源点最小的顶点
u。 - 遍历
u的邻居v,尝试松弛边(u, v): [ \text{dist}[v] = \min(\text{dist}[v], \text{dist}[u] + \text{weight}(u, v)) ] - 重复步骤 3-4,直到所有顶点处理完。
三、C++ 模板实现
这里给出使用 优先队列(min-heap) 的高效实现:
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9; // 定义无穷大
const int MAXN = 100005;
struct Edge {
int to, weight;
};
vector<Edge> adj[MAXN]; // 邻接表存储图
int dist[MAXN]; // 源点到各点最短距离
bool visited[MAXN]; // 标记是否已处理
void dijkstra(int source, int n) {
for (int i = 1; i <= n; i++) {
dist[i] = INF;
visited[i] = false;
}
dist[source] = 0;
// 优先队列存储 pair<距离, 节点>
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
pq.push({0, source});
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
if (visited[u]) continue; // 已处理则跳过
visited[u] = true;
for (auto &edge : adj[u]) {
int v = edge.to, w = edge.weight;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
pq.push({dist[v], v});
}
}
}
}
int main() {
int n, m;
cin >> n >> m; // n个顶点,m条边
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back({v, w});
// 若是无向图,加上这一行
// adj[v].push_back({u, w});
}
int source;
cin >> source;
dijkstra(source, n);
for (int i = 1; i <= n; i++) {
if (dist[i] == INF) cout << "INF\n";
else cout << dist[i] << "\n";
}
return 0;
}