Sắp Xếp Tôpô
đã đăng vào 1 tháng 4 năm 2025, 12:11 a.m.
🧮 Cheatsheet: Sắp Xếp Tôpô (Topological Sort)
📘 Giới thiệu
Sắp xếp tôpô (topological sort) là một kỹ thuật duyệt đồ thị có hướng (DAG) sao cho nếu tồn tại cạnh từ u → v
thì u
sẽ xuất hiện trước v
trong thứ tự sắp xếp.
🧠 Ứng dụng
- Sắp xếp thứ tự thực hiện công việc có phụ thuộc.
- Lập lịch bài học, xây dựng module hệ thống.
- Phân tích biểu thức, trình biên dịch.
- Bài toán kiểm tra chu trình trong đồ thị có hướng.
🔁 Code C++ (BFS - Kahn’s Algorithm)
#include <bits/stdc++.h>
using namespace std;
vector<int> topo_sort(int n, vector<vector<int>>& adj) {
vector<int> in_degree(n + 1, 0);
for (int u = 1; u <= n; ++u)
for (int v : adj[u])
in_degree[v]++;
queue<int> q;
for (int i = 1; i <= n; ++i)
if (in_degree[i] == 0)
q.push(i);
vector<int> topo;
while (!q.empty()) {
int u = q.front(); q.pop();
topo.push_back(u);
for (int v : adj[u]) {
if (--in_degree[v] == 0)
q.push(v);
}
}
if (topo.size() < n)
throw runtime_error("Graph has a cycle");
return topo;
}
🔁 Code C++ (DFS)
void dfs(int u, vector<vector<int>>& adj, vector<bool>& visited, stack<int>& st) {
visited[u] = true;
for (int v : adj[u])
if (!visited[v])
dfs(v, adj, visited, st);
st.push(u);
}
vector<int> topo_sort_dfs(int n, vector<vector<int>>& adj) {
vector<bool> visited(n + 1, false);
stack<int> st;
for (int i = 1; i <= n; ++i)
if (!visited[i])
dfs(i, adj, visited, st);
vector<int> topo;
while (!st.empty()) {
topo.push_back(st.top());
st.pop();
}
return topo;
}
📊 So sánh BFS và DFS
Tiêu chí | BFS (Kahn's) | DFS-Based |
---|---|---|
Phát hiện chu trình | Có (qua số lượng đỉnh) | Không trực tiếp |
Dễ debug | ✅ | ❌ |
Dễ cài đặt | ✅ | ✅ |
Hiệu suất | Ngang nhau | Ngang nhau |
⏱️ Độ phức tạp
- Thời gian: O(V + E)
- Không gian: O(V + E)
✅ Ưu điểm
- Hiệu quả với đồ thị DAG.
- Cài đặt đơn giản.
- Có thể dùng phát hiện chu trình (Kahn’s Algorithm).
❌ Nhược điểm
- Chỉ dùng được với đồ thị có hướng không chu trình (DAG).
- Với đồ thị có chu trình sẽ không tồn tại thứ tự topo.
🔧 Tối ưu
- Dùng
priority_queue
thay vìqueue
để tìm topo theo thứ tự từ điển nhỏ nhất. - Gộp
visited
+in_degree
thành 1 mảng nếu tiết kiệm bộ nhớ.
🤔 Khi nào dùng?
Tình huống | Có nên dùng? |
---|---|
Đồ thị có hướng, không chu trình (DAG) | ✅ |
Bài toán lập lịch, sắp xếp có phụ thuộc | ✅ |
Đồ thị có chu trình | ❌ (không áp dụng) |
Tìm chu trình trong đồ thị | Dùng biến thể của Kahn ✅ |
📚 Tham khảo
- CP-Algorithms - Topological Sort
- Atcoder, Codeforces, CSES Graph Section
Nhận xét