Explore all courses in this category.
Explore all courses in this category.
Nguyễn Đình Cường
0 comment
09 Nov, 2026
Mạng xã hội, bản đồ đường đi, hệ thống tàu điện: tất cả đều là các điểm được nối với nhau bằng đường. Trong khoa học máy tính, mô hình đó gọi là đồ thị, và nó giải quyết rất nhiều bài toán thực tế.
Đồ thị (graph) gồm tập các đỉnh (vertex/node) và tập các cạnh (edge) nối các đỉnh với nhau. Một vài phân loại quan trọng:
Cây thực ra là một trường hợp đặc biệt của đồ thị: liên thông và không có chu trình.
Hai cách phổ biến nhất:
do_thi = {
"A": ["B", "C"],
"B": ["A", "D"],
"C": ["A", "D"],
"D": ["B", "C", "E"],
"E": ["D"],
}BFS thăm các đỉnh theo từng "vòng": đầu tiên các đỉnh cách xuất phát 1 bước, rồi 2 bước... Nó dùng hàng đợi và tìm được đường đi ít cạnh nhất trong đồ thị không trọng số.
from collections import deque
def bfs(do_thi, bat_dau):
da_tham = {bat_dau}
hang = deque([bat_dau])
thu_tu = []
while hang:
u = hang.popleft()
thu_tu.append(u)
for v in do_thi[u]:
if v not in da_tham:
da_tham.add(v)
hang.append(v)
return thu_tu
print(bfs(do_thi, "A")) # ['A', 'B', 'C', 'D', 'E']DFS đi sâu hết mức theo một nhánh rồi mới quay lại. Có thể viết đệ quy (dùng ngăn xếp lời gọi) hoặc dùng stack tường minh.
def dfs(do_thi, u, da_tham=None):
if da_tham is None:
da_tham = set()
da_tham.add(u)
print(u, end=" ")
for v in do_thi[u]:
if v not in da_tham:
dfs(do_thi, v, da_tham)
dfs(do_thi, "A") # A B D C ETập da_tham rất quan trọng: nếu thiếu nó, chương trình sẽ đi vòng quanh chu trình mãi mãi.
| Mục đích | Gợi ý |
|---|---|
| Tìm đường ngắn nhất (ít bước) | BFS |
| Kiểm tra hai đỉnh có liên thông | BFS hoặc DFS |
| Phát hiện chu trình, sắp xếp tô-pô | DFS |
| Giải mê cung, thử mọi khả năng (quay lui) | DFS |
BFS cực kỳ hợp với bài toán lưới. Mê cung dưới đây dùng # cho tường, . cho đường đi:
from collections import deque
me_cung = ["..#.",
".##.",
"....",
"#..."]
def duong_ngan_nhat(luoi, bd, dich):
h, w = len(luoi), len(luoi[0])
hang = deque([(bd, 0)])
da_tham = {bd}
while hang:
(r, c), d = hang.popleft()
if (r, c) == dich:
return d
for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nr, nc = r + dr, c + dc
if 0 <= nr < h and 0 <= nc < w and luoi[nr][nc] == "." and (nr, nc) not in da_tham:
da_tham.add((nr, nc))
hang.append(((nr, nc), d + 1))
return -1
print(duong_ngan_nhat(me_cung, (0, 0), (0, 3))) # 7Mỗi ô là một đỉnh, bốn ô kề là các cạnh. Vì BFS thăm theo từng lớp khoảng cách nên lần đầu chạm đích chính là đường ngắn nhất. Hãy thử thay đổi mê cung và xem kết quả.
Bài tập: đếm số thành phần liên thông của một đồ thị, và đếm số "hòn đảo" trong lưới 0/1 (các ô 1 kề nhau tạo thành một đảo).
Đồ thị mô hình hóa mọi mối quan hệ, và chỉ cần hiểu danh sách kề cùng BFS, DFS là bạn đã giải được rất nhiều bài toán. Hãy thử mô hình hóa một bài toán quen thuộc như bản đồ lớp học hay mạng bạn bè thành đồ thị rồi tự duyệt nó.
Học xong lý thuyết, hãy thực hành thật nhiều; các bài giảng có bài tập trong khóa học codebem.com sẽ giúp bạn việc đó.
Nguyễn Đình Cường
0 comment