SPFA (Shortest Path Faster Algorithm)¶
Tác giả: FPTOJ Team
Nội dung tham khảo từ: VNOI Wiki, CP-Algorithms - SPFA
1. Bản chất vấn đề¶
Bài toán: Tìm đường đi ngắn nhất có cạnh âm¶
Cho đồ thị có trọng số (có thể âm). Tìm đường đi ngắn nhất từ đỉnh \(S\).
- Dijkstra: Không hoạt động với cạnh âm.
- Bellman-Ford: \(O(NM)\) — đúng nhưng chậm.
- SPFA: Cải tiến Bellman-Ford — trung bình \(O(M)\), worst case \(O(NM)\).
So sánh¶
| Thuật toán | Trọng số âm | Trung bình | Worst case |
|---|---|---|---|
| Dijkstra | Không | \(O(M \log N)\) | \(O(M \log N)\) |
| Bellman-Ford | Có | \(O(NM)\) | \(O(NM)\) |
| SPFA | Có | \(O(M)\) | \(O(NM)\) |
2. Tư duy cốt lõi¶
Ý tưởng: Chỉ cập nhật đỉnh thay đổi¶
Bellman-Ford lặp \(N-1\) lần, mỗi lần duyệt tất cả cạnh. SPFA chỉ duyệt cạnh từ đỉnh vừa được cập nhật (dùng queue).
Trace chi tiết¶
Đồ thị: 4 đỉnh, 5 cạnh.
| Cạnh | Trọng số |
|---|---|
| \(0 \to 1\) | 2 |
| \(0 \to 2\) | 3 |
| \(1 \to 3\) | 1 |
| \(2 \to 1\) | -2 |
| \(2 \to 3\) | 4 |
SPFA từ đỉnh 0:
| Bước | Queue (trái → phải) | Xử lý | Cập nhật | dist[] |
|---|---|---|---|---|
| 0 | \([0]\) | 0 | \(dist[0] = 0\), thêm 1 (w=2), thêm 2 (w=3) | \([0, \infty, \infty, \infty]\) |
| 1 | \([1, 2]\) → pop 1 | 1 | \(dist[1] = 2\) (qua 0→1), thêm 3 (w=1) | \([0, 2, 3, \infty]\) |
| 2 | \([2, 3]\) → pop 2 | 2 | \(dist[1] = \min(2, 3+(-2)) = 1\) → cập nhật, thêm 1; \(dist[3] = 3+4 = 7\), thêm 3 | \([0, 1, 3, 7]\) |
| 3 | \([3, 1]\) → pop 3 | 3 | Không cập nhật gì | \([0, 1, 3, 7]\) |
| 4 | \([1]\) → pop 1 | 1 | \(dist[3] = \min(7, 1+1) = 2\) → cập nhật, thêm 3 | \([0, 1, 3, 2]\) |
| 5 | \([3]\) → pop 3 | 3 | Không cập nhật gì | \([0, 1, 3, 2]\) |
Kết quả: \(dist = [0, 1, 3, 2]\)
Kiểm tra chu trình âm¶
Nếu 1 đỉnh được cập nhật \(\ge N\) lần \(\Rightarrow\) tồn tại chu trình âm.
3. Phân tích tính đúng đắn¶
Tại sao SPFA đúng?¶
Tương tự Bellman-Ford: mỗi lần 1 đỉnh \(u\) được đưa vào queue và xử lý, nó cập nhật khoảng cách cho các đỉnh kề. Nếu khoảng cách cải thiện, đỉnh kề được thêm vào queue.
Khi queue rỗng, mọi đường đi ngắn nhất đã được tìm thấy (tương tự Bellman-Ford hội tụ).
Worst case \(O(NM)\)¶
Khi đồ thị là chuỗi: \(0 \to 1 \to 2 \to \ldots \to N-1\), mỗi đỉnh có thể được cập nhật \(O(N)\) lần.
4. Đánh giá độ phức tạp¶
| Thuật toán | Trung bình | Worst case | Không gian |
|---|---|---|---|
| Bellman-Ford | \(O(NM)\) | \(O(NM)\) | \(O(N + M)\) |
| SPFA | \(O(M)\) | \(O(NM)\) | \(O(N + M)\) |