Professional Documents
Culture Documents
(DFS VÀ BFS)
I. Giới thiệu.
1. Lý thuyết đồ thị cơ bản.
- Trong toán học và tin học, đồ thị là 1 phần của lý thuyết đồ thị. Đồ thị nói
theo cách dễ hiểu là 1 tập hợp các đỉnh được nối với nhau bởi các cạnh.
Một đồ thị cơ bản được vẽ dưới dạng một tập các điểm (đỉnh, nút) nối với
nhau bởi các cạnh (đoạn thẳng), các cạnh có thể có hướng hoặc vô hướng
(tùy vào yêu cầu của đề bài).
2 1
1 2
3
5
6 3
4 4
5
H1 H2
Một đồ thị G = (V, E) bao gồm V là tập hợp chứa đỉnh, còn E là tập hợp
chứa các cạnh. Trong bài viết, ta đề cập đến hai loại đồ thị, đồ thị có hướng
và đồ thị vô hướng
- Đồ thị vô hướng là đồ thị mà mà giữa hai đỉnh của một cạnh không có thứ
tự. Trong ví dụ trên, đồ thị bên trái (H1) G = (V, E) có tập đỉnh V = {1, 2, 3,
4, 5, 6} và tập cạnh E = {(1, 2), (1, 3), (1, 4), (2, 3), (2, 5), (2, 4), (3, 5),
(3,6), (5, 6), (2, 1), (3, 1), (4, 1), (3, 2), (5, 2), (4, 2), (5, 3), (6, 3), (6, 5)}
- Đồ thị có hướng là đồ thị mà giữa hai đỉnh của một cạnh luôn có thứ tự.
Trong ví dụ trên, đồ thị bên phải (H2) G = (V, E) có tập đỉnh V = {1, 2, 3, 4,
5} và tập cạnh E = {(1,2), (1, 5), (1, 4), (2, 3), (3, 1), (3, 5), (3, 4), (4, 5)}
1 2 3 4 5 6
1
0 1 1 1 0 0
2
1 0 1 1 1 0
3
1 1 0 0 1 1
4
1 1 0 0 0 0
5
0 1 1 0 0 1
6
0 0 1 0 1 0
Dễ thấy ma trận kề của đồ thị vô hướng là ma trận đối xứng, ma trận của
một đồ thị có hướng chưa chắc đã là ma trận đối xứng
- Danh sách cạnh:
Chúng ta cần khởi tạo hai mảng là mảng đầu a[m] chứa các đỉnh đầu tiên
của cạnh và mảng cuối b[m] chứa các đỉnh cuối cùng của cạnh.
Ví dụ:
Đồ thị G = (V, E) có tập đỉnh V = {1, 2, 3, 4, 5, 6} và tập cạnh E = {(1, 2),
(1, 3), (1, 4), (2, 3), (2, 5), (2, 4), (3, 5), (3,6), (5, 6), (2, 1), (3, 1), (4, 1), (3,
2), (5, 2), (4, 2), (5, 3), (6, 3), (6, 5)}. Danh sách cạnh của đồ thị G sẽ có
dạng như sau :
Đầu 1 1 1 2 2 2 3 3 5
Cuối 2 3 4 3 5 4 5 6 6
2 5
1
11
4
3
Thứ tự các bước đệ quy sẽ như sau DFS (1) => DFS (2) => DFS (4) =>
DFS(5) => DFS (3);
Code C++: với input là danh sách kề, duyệt theo thứ tự từ bé đến lớn
#include <bits/stdc++.h>
int main ()
{
int n, m; cin >> n >> m;
for (int i =0; i < m; i++)
{
int x, y; cin >> x >> y;
adj[x].push_back (y);
adj[y].push_back (x);
}
for (int i = 1; i <= n; i++)
{
sort (adj[i].begin(), adj[i].end());
}
DFS (1);
}
2 5
Thứ tự các đỉnh trong hàng đợi sẽ như sau (phần tử đầu tiên là phân tử đầu
hàng đợi): 1 2 3 4 5
Code C++: input là danh sách cạnh, duyệt theo thứ tự từ bé đến lớn
#include <bits/stdc++.h>
int main ()
{
int n, m; cin >> n >> m;
for (int i = 0; i < m; i++)
{
int x, y; cin >> x >> y;
adj[x].push_back (y);
adj[y].push_back (x);
}
for (int i = 1; i <= n; i++)
{
sort (adj[i].begin(), adj[i].end());
}
BFS (1);
}