| 项目 | 值 |
|---|---|
| 主题 | 最短路径 |
| 核心概念 | 贪心选距离源点最近的未访问顶点,用它更新其他顶点的距离 |
| 时间复杂度 | Dijkstra $O(|V|^2)$(邻接矩阵);Floyd $O(|V|^3)$ |
| 难度 | ⭐⭐⭐⭐ |
| 重要性 | ⭐⭐⭐⭐⭐ |
贪心策略,每次选择距离源点最近的未访问顶点,用它更新其他顶点的距离。
void Dijkstra(MGraph G, int v0) {
int dist[MaxVertexNum], path[MaxVertexNum];
bool visited[MaxVertexNum];
for (int i = 0; i < G.vexnum; i++) {
dist[i] = G.edge[v0][i];
path[i] = (dist[i] < INF) ? v0 : -1;
visited[i] = false;
}
dist[v0] = 0; visited[v0] = true;
for (int i = 1; i < G.vexnum; i++) {
int min = INF, u = -1;
for (int j = 0; j < G.vexnum; j++)
if (!visited[j] && dist[j] < min) { min = dist[j]; u = j; }
visited[u] = true;
for (int w = 0; w < G.vexnum; w++)
if (!visited[w] && dist[u] + G.edge[u][w] < dist[w]) {
dist[w] = dist[u] + G.edge[u][w];
path[w] = u;
}
}
}
时间复杂度 $O(|V|^2)$。
$$A^{(k)}[i][j] = \min\big(A^{(k-1)}[i][j],\; A^{(k-1)}[i][k] + A^{(k-1)}[k][j]\big)$$
void Floyd(MGraph G) {
int A[MaxVertexNum][MaxVertexNum];
for (int i = 0; i < G.vexnum; i++)
for (int j = 0; j < G.vexnum; j++)
A[i][j] = G.edge[i][j];
for (int k = 0; k < G.vexnum; k++) // k 必须在最外层
for (int i = 0; i < G.vexnum; i++)
for (int j = 0; j < G.vexnum; j++)
if (A[i][k] + A[k][j] < A[i][j])
A[i][j] = A[i][k] + A[k][j];
}
时间复杂度 $O(|V|^3)$。
| 特性 | Dijkstra | Floyd |
|---|---|---|
| 类型 | 单源最短路径 | 多源最短路径 |
| 时间 | $O(|V|^2)$ | $O(|V|^3)$ |
| 负权边 | 不允许 | 不允许负权回路 |
| 适用 | 一个源点到所有点 | 任意两点 |
| 步骤 | 选 u | dist 更新 |
|---|---|---|
| 初始化 | — | $[0, 10, 5, 1, \infty]$ |
| 1 | D(1) | $[0, 10, 5, 0, 7]$ |
| 2 | C(5) | $[0, 8, 0, 0, 7]$ |
| 3 | E(7) | $[0, 8, 0, 0, 0]$ |
| 4 | B(8) | $[0, 0, 0, 0, 0]$ |
最短路径:A→D:1,A→C:5,A→E:7(A→D→E),A→B:8(A→C→B)。
0 1 2
0 [ 0 4 11 ]
1 [ 6 0 2 ]
2 [ 3 999 0 ]
依次允许经过中间顶点 0、1、2,最终:
0 1 2
0 [ 0 4 6 ]
1 [ 5 0 2 ]
2 [ 3 7 0 ]
例如 $A[1][0]=5$ 对应路径 $1→2→0$($2+3=5$)。
| 算法 | 时间 | 空间 | 限制 |
|---|---|---|---|
| Dijkstra | $O(|V|^2)$ | $O(|V|)$ | 无负权边 |
| Floyd | $O(|V|^3)$ | $O(|V|^2)$ | 无负权回路 |
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。