You are on page 1of 24

CHUYÊN ĐỀ

LÝ THUYẾT ĐỒ THỊ
CÁC THUẬT TOÁN TÌM KIẾM
TRÊN ĐỒ THỊ
NỘI DUNG
CHÍNH
Bài toán tìm Đường
đi

Biểu diễn Đồ thị

Tìm kiếm theo chiều


sâu

Tìm kiếm theo chiều


rộng
Bài toán tìm Đường đi
1 BT quan trọng trong LTĐT là BT duyệt tất cả các
đỉnh có thể đến được từ 1 đỉnh xuất phát nào đó
Với một đồ thị có nhiều nút, việc kiểm tra tính liên
thông của đồ thị là bài toán lớn, cần có cách thức
để thực hiện nhanh, chính xác.
Hai cách duyệt đồ thị phổ biến được áp dụng:
1. Duyệt đồ thị theo chiều sâu (Depth First Search -
DFS)
2. Duyệt đồ thị theo chiều rộng (Breadth First Search
- BFS)

BFS
DFS
Phần 3.1
TÌM KIẾM THEO CHIỀU SÂU (Depth
First Search – DFS)

Giảng viên: Nguyen Ngoc Trung


nguyenngoctrung.dhsp@gmail.com
3. Duyệt đồ thị

3.2 Duyệt đồ thị theo chiều sâu


Xuất từ một đỉnh v bất kỳ của đồ thị G, chúng ta thực
hiện như sau:
Bước 1: đánh dấu v đã được duyệt.
Bước 2: thực hiện đánh dấu đã duyệt với mỗi đỉnh
w chưa duyệt kề với v,
Bước 3: làm lại bước 2 cho đến khi tất cả các đỉnh
được duyệt.

DFS
3. Duyệt đồ thị

3.2 Duyệt đồ thị theo chiều sâu


Ví dụ:
Thực hiện duyệt đồ thị theo chiều sâu trên đồ
thị G dưới đây:
v1 v2 v3 v4

v5 v6 v7 v8

Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8
Bảng duyệt v1 v2 v6 v3 v4 v8 v7 v5
Ví dụ về DFS
• Áp dụng DFS, hãy thể hiện thứ tự duyệt
các đỉnh trong đồ thị sau: u

0 t v

s x

Đáp án: 0 1 2 3 4 9 5 6 7 8 10 Đáp án: t u s v


Đỉnh x không được duyệt

05/18/20 Lý thuyết đồ thị 8


Khai báo dữ liệu // ma trận kề
A: array[1..250,1..250] of boolean;
// đánh dấu đỉnh đã duyệt
ok: array[1..250] of boolean;
N,m,i,u,v,dem: integer;

Procedure DFS(u:integer);
Var i:integer;
Begin
For i:=1 to N do
if ok[i] and(A[u,i])then
begin
ok[i]:=false;
DFS(i);
end;
end;

05/18/20 Lý thuyết đồ thị 9


Đếm số TPLT trong ĐT

05/18/20 Lý thuyết đồ thị 10


Phần 3.2
TÌM KIẾM THEO CHIỀU RỘNG
(Breadth First Search - BFS)

Giảng viên: Nguyen Ngoc Trung


nguyenngoctrung.dhsp@gmail.com
3. Duyệt đồ thị

3.3 Duyệt đồ thị theo chiều rộng


Xuất từ một đỉnh v bất kỳ của đồ thị G, chúng ta thực hiện
như sau:
Bước 1: đánh dấu đã duyệt cho một đỉnh v bất kỳ.
Bước 2: chọn đỉnh v đã được duyệt nhưng có đỉnh kề
chưa được duyệt. Việc chọn đỉnh v được xét ưu tiên cho
các đỉnh được đánh dấu duyệt sớm.
Bước 3: thực hiện đánh dấu đã duyệt với tất cả các đỉnh
w kề với v,
Bước 4: làm lại bước 2 cho đến khi tất cả các đỉnh được
duyệt.

BFS
3. Duyệt đồ thị

3.3 Duyệt đồ thị theo chiều rộng


3. Duyệt đồ thị

3.3 Duyệt đồ thị theo chiều rộng


Ví dụ:
Thực hiện duyệt đồ thị theo chiều rộng trên đồ
thị G dưới đây:
v1 v2 v3 v4

v5 v6 v7 v8

Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8
Bảng duyệt v1 v2 v5 v6 v3 v7 v4 v8
3. Duyệt đồ thị

3.3 Duyệt đồ thị theo chiều rộng


Ví dụ:
Thực hiện duyệt đồ thị theo chiều rộng trên đồ
thị G dưới đây:

Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9
Cài đặt BFS (tt)
1 2 3
• Đưa 1 vào Queue
• Lấy 1 ra xử lý, đưa 5, 4, 2 vào Queue
• Lấy 2 ra xử lý, đưa 5, 3 vào Queue
• Lấy 4 ra xử lý, đưa 5 vào Queue 4 6
5 6
• Lấy 5 ra xử lý, đưa 3 vào Queue 3
• Lấy 3 ra xử lý. Đưa 6 vào Queue 5
• Lấy 5 ra. Không xử lý (vì đã xử lý rồi) 5 Queue
• Lấy 5 ra. Không xử lý 3
5
• Lấy 3 ra. Không xử lý
4
• Lấy 6 ra xử lý. Không đưa gì vào Queue
1
2

Thứ tự 1 2 4 5 3 6
duyệt:

05/18/20 Lý thuyết đồ thị 16


Ví dụ về BFS
• Áp dụng DFS, hãy thể hiện thứ tự duyệt
các đỉnh trong đồ thị sau: u

0 t v

s x

Đáp án: 0 1 3 9 2 4 5 6 8 10 7 Đáp án: t u s v


Đỉnh x không được duyệt

05/18/20 Lý thuyết đồ thị 17


Phần 3.3
ỨNG DỤNG CÁC THUẬT TOÁN TÌM
KIẾM TRÊN ĐỒ THỊ

Giảng viên: Nguyen Ngoc Trung


nguyenngoctrung.dhsp@gmail.com
Hàm DFS bằng đệ quy
 Do nguyên tắc gọi hàm đệ quy cũng giống như nguyên tắc hoạt
động của Stack nên ta có thể dùng đệ quy thay cho Stack để viết
hàm DFS
 Chú ý:
 Mảng danhdau bắt buộc phải khai báo bên ngoài hàm đệ quy
 Phần khởi tạo mảng danhdau cũng vẫn được thực hiện nhưng phải
để ở bên ngoài hàm đệ quy (thường khởi tạo ở trong hàm main).

int danhdau[maxV]
void DFS(DOTHI g, int s) // s la dinh xuat phat
{
if (danhdau[s] ==1) return;
cout<<s<<“ da duoc duyet \n“;danhdau[s] = 1;
for (int v = 1; v<=g.nV; v++)
if (danhdau[v] == 0&&g.mtke[s][v]!=0)
DFS(g,v);
}
Lý thuyết đồ thị 05/18/20 19
Áp dụng DFS để kiểm tra
liên thông
• Ý tưởng:
• Áp dụng cho đồ thị vô hướng
• Áp dụng DFS, bắt đầu từ đỉnh bất kỳ, nếu duyệt
qua được tất cả các đỉnh thì đồ thị là liên thông
• Cụ thể:
• Sử dụng thêm biến dem để đếm số đỉnh được
duyệt
• Nếu duyệt xong mà đếm bằng g.nV (số đỉnh của
đồ thị) thì có nghĩa là tất cả các đỉnh được duyệt
Áp dụng DFS để kiểm tra liên thông (tt)
int danhdau[maxV]
void DFS_lt(DOTHI g, int s, int &dem) // s la dinh xuat phat
{
//Khoi tao mang danh dau trong ham main hoac ben ngoai ham nay
cout<<s<<“ da duoc duyet \n“; dem++; danhdau[s] = 1;
for (int v = 1; v<=g.nV; v++)
if (danhdau[v] == 0)
DFS(g,v);
}

int isLienThong(DOTHI g)
{
if (g.type == 1)
return 0; // khong xet do thi co huong
int dem = 0;
for (int v = 1; v<= g.nV; v++)
danhdau[v] = 0;
DFS_lt(g,1,dem);
if (dem == g.nV)
return 1; // do thi lien thong
return 0;
}
Ví dụ về DFS GRAPH.IN GRAPH.OUT
P
8715 1, 2, 3, 5, 4, 6
12 5<- 3<-2<-1
2 4 13
6 23
24
1 35
46
7
78

8
3 5

05/18/20 Lý thuyết đồ thị 22


2 4 2 4
6 6
1
7 1
8 7
3 5
8
3 5

05/18/20 Lý thuyết đồ thị 23


Áp dụng DFS để tìm đường
đi
• Ý tưởng:

You might also like