作者:July、sunbaigui | 日期:2011年3月25日
| 算法 | 數據結構 | 時間複雜度 | 適用場景 |
|---|---|---|---|
| Dijkstra | 數組 | O(V² + E) | 稠密圖 |
| Dijkstra | 二叉堆 | O((V+E) log V) | 稀疏圖 |
| Dijkstra | 斐波那契堆 | O(V log V + E) | 理論最優 |
| Bellman-Ford | 隊列 | O(VE) | 含負權邊、判負環 |
| SPFA | 隊列優化 | O(kE), k≪V | 實際最快、含負權 |
SPFA(G, w, s):
INITIALIZE-SINGLE-SOURCE(G, s)
Q ← ∅
for each v ∈ V[G]: q[v] = 0
ENQUEUE(Q, s); q[s] = 1
while Q ≠ ∅:
u ← DEQUEUE(Q); q[u] = 0
for each edge (u,v) ∈ E[G]:
t ← d[v]
RELAX(u, v, w)
π[v] ← u
if d[v] < t and q[v] == 0:
ENQUEUE(Q, v); q[v] = 1
struct Node {
int to, dist, cost; // 目標點、長度、花費
};
vector graph[1005];
int d[1005][2]; // d[i][0]=最短距離, d[i][1]=對應最小花費
bool inQueue[1005];
void spfa(int s) {
for (int i = 1; i <= N; i++) d[i][0] = d[i][1] = INF;
d[s][0] = d[s][1] = 0;
queue q;
q.push(s); inQueue[s] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
inQueue[u] = false;
for (auto& e : graph[u]) {
int v = e.to;
int nd = d[u][0] + e.dist;
int nc = d[u][1] + e.cost;
// 距離更短,或距離相等但花費更小
if (nd < d[v][0] || (nd == d[v][0] && nc < d[v][1])) {
d[v][0] = nd;
d[v][1] = nc;
if (!inQueue[v]) {
q.push(v);
inQueue[v] = true;
}
}
}
}
}
SPFA 以隊列優化 Bellman-Ford,兼具負權支持與高效能,是解決單源最短路(含雙權重變體)的實戰首選。浙大真題通過雙維距離數組優雅處理「距離優先、花費次之」的多目標優化需求。掌握 SPFA 核心邏輯與變體擴展,是算法競賽與工程實戰的必備技能。