TieuLuanCauTrucRoiRac

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 49

BỘ GIÁO DỤC VÀ ĐÀO TẠO

TRƯỜNG ĐẠI HỌC GIAO THÔNG VẬN TẢI THÀNH PHỐ HỒ CHÍ MINH
 KHOA CÔNG NGHỆ THÔNG TIN 

Môn học: Cấu trúc rời rạc


ĐỀ TÀI TIỂU LUẬN
“TÌM KIẾM TRÊN ĐỒ THỊ- ĐỒ THỊ EULER VÀ ĐỒ THỊ HAMILTON
CÂY VÀ CÂY KHUNG CỦA ĐỒ THỊ
TÌM ĐƯỜNG ĐI NGẮN NHẤT ’’

Giảng viên : Trần Thế Vinh


Sinh viên thực hiện : Trần Minh Thái-051205002504
Lớp học phần: CN2301C-010112204401
Năm học: 2024-2025

TP Hồ Chí Minh, Tháng 6, năm 2024.


MỤC LỤC
PHẦN I: MỞ ĐẦU

1. Lời Mở Đầu ..............................................................................................................................


2. Mục đích ...................................................................................................................................
3. Đối tượng ..................................................................................................................................
PHẦN II: NỘI DUNG
CHƯƠNG 1: ĐỒ THỊ, TÍNH LIÊN THÔNG VÀ PHƯƠNG PHÁP MA TRẬN KỀ
A. Sơ Lược về đồ thị.........................................................................................................................
B. Biểu diễn đồ thị và Phương pháp ma trận kề ...........................................................................
C. Tính liên thông và kiểm tra tính liên thông...............................................................................
CHƯƠNG 2: TÌM KIẾM TRÊN ĐỒ THỊ - ĐỒ THỊ EULER VÀ ĐỒ THỊ HAMILTON
A. Đồ thị Euler
I. Khái niệm................................................................................................................................
II. Định Lý....................................................................................................................................
III. Thuật toán (mã giải)...............................................................................................................
IV. Sơ đồ khối................................................................................................................................
V. Code, Input/Output ...............................................................................................................
VI. Tìm đường đi ngắn nhất.........................................................................................................
B. Đồ thị Hamilton
I. Khái niệm................................................................................................................................
II. Định lý-Nhận xét.....................................................................................................................
III. Thuật toán (mã giải)-Tìm 1 đường đi Hamiton bất kì........................................................
IV. Sơ đồ khối................................................................................................................................
V. Code, Input/Output................................................................................................................
C. Ưu và Nhược điểm, so sánh 2 thuật toán......................................................................................
CHƯƠNG 3: CÂY VÀ KHUNG CỰC TIỂU CỦA ĐỒ THỊ
A. Thuật toán Prim
I. Khái niệm.....................................................................................................................................
II. Điều kiện tồn tại..........................................................................................................................
III. Thuật toán (mã giải)...................................................................................................................
IV. Sơ đồ khối....................................................................................................................................
V. Code, Input/Output.....................................................................................................................
B. Thuật toán Kruskal
I. Khái niệm....................................................................................................................................
II. Điều kiện tồn tại.........................................................................................................................
III. Thuật toán (mã giải)..................................................................................................................
IV. Sơ đồ khối...................................................................................................................................
V. Code, Input/Output....................................................................................................................
C. Ưu và Nhược điểm, so sánh 2 thuật toán......................................................................................
CHƯƠNG 4: TÌM ĐƯỜNG ĐI NGẮN NHẤT
A. Bài toán đường đi ngắn nhất.........................................................................................................
B. Thuật toán Dijkstra
I. Khái niệm.....................................................................................................................................
II. Điều kiện tồn tại..........................................................................................................................
III. Thuật toán (mã giải)...................................................................................................................
IV. Sơ đồ khối....................................................................................................................................
V. Code, Input/Output.....................................................................................................................
C. Thuật toán Bellman – Ford
I. Khái niệm.....................................................................................................................................
II. Điều kiện tồn tại..........................................................................................................................
III. Thuật toán (mã giải)...................................................................................................................
IV. Sơ đồ khối....................................................................................................................................
V. Code, Input/Output.....................................................................................................................
D. Ưu và Nhược điểm, so sánh 2 thuật toán.....................................................................................

PHẦN III: KẾT LUẬN.................................................................................................................

TÀI LIỆU THAM KHẢO.............................................................................................................


PHẦN I: MỞ ĐẦU

1. Lời Mở Đầu:

Trong lĩnh vực khoa học máy tính, cấu trúc rời rạc đồ thị luôn được coi là quan
trọng trong việc mô hình hóa và giải quyết các vấn đề phức tạp. Trên thế giới này, vai
trò của đồ thị được xem xét một cách sâu sắc. Trong bài viết này, khám phá về tìm kiếm
trên đồ thị sẽ được tiến hành, bao gồm cả việc nghiên cứu về đồ thị Euler và Hamilton,
cũng như cấu trúc cây và khung cực tiểu của đồ thị.

Bắt đầu bằng việc tìm hiểu về hoạt động của thuật toán Euler và Hamilton trong
việc bao phủ từng cạnh của đồ thị một cách duy nhất. Tiếp theo, khám phá về cây và
khung cực tiểu, hai khái niệm quan trọng trong việc phân tích cấu trúc của đồ thị sẽ được
tiến hành. Ngoài ra, thuật toán Bellman-Ford cũng sẽ được xem xét để tìm hiểu cách
giải quyết các bài toán về con đường ngắn nhất trong đồ thị có trọng số âm.

Tập trung vào việc tìm kiếm con đường ngắn nhất trong đồ thị thông qua thuật
toán Dijkstra sẽ được đi vào chi tiết. Cuối cùng, hai phương pháp tìm cây bao trùm nhỏ
nhất - thuật toán Prim và Kruskal - sẽ được xem xét kỹ lưỡng.

Với sự kết hợp của các thuật toán này, bài viết sẽ mang đến một cái nhìn tổng
quan và chi tiết về cách sử dụng và ứng dụng các cấu trúc và thuật toán đồ thị trong khoa
học máy tính.

4
2. Mục đích :

Mục Đích:
• Tìm hiểu và phân tích các thuật toán quan trọng trong lĩnh vực đồ thị: Prim,
Kruskal, Dijkstra, Bellman – Ford, Euler và Hamilton.
• Cài đặt và thực thi các thuật toán trên máy tính để hiểu rõ cách hoạt động và
ứng dụng của chúng.
• So sánh hiệu suất và độ phức tạp tính toán của các thuật toán để đưa ra nhận
xét và đánh giá về tính hiệu quả của mỗi thuật toán.

3. Đối tượng :

Đối Tượng:
• Sinh viên, học viên, và những người quan tâm đến lĩnh vực thuật toán và đồ
thị.
• Các nhà nghiên cứu và chuyên gia trong lĩnh vực khoa học máy tính và toán
học.
• Giảng viên và sinh viên đang nghiên cứu hoặc giảng dạy về các thuật toán đồ
thị.

5
PHẦN II : NỘI DUNG

CHƯƠNG 1: GIỚI THIỆU TỔNG QUAN VỀ KHO HÀNG NGOẠI QUAN

1. ĐỒ THỊ, TÍNH LIÊN THÔNG VÀ PHƯƠNG PHÁP MA TRẬN KỀ:


A. Sơ Lược về đồ thị
Khái niệm:
- Đồ thị là một cấu trúc toán học gồm hai tập: tập các đỉnh (nodes) và tập các cạnh
(edges).
- Mỗi cạnh nối hai đỉnh và có thể có hướng hoặc vô hướng.
- Đồ thị được biểu diễn bằng hình vẽ, với đỉnh là các điểm và cạnh là các đường nối
giữa các điểm.
Phân loại:
- Đồ thị vô hướng: Cạnh không có hướng.
- Đồ thị có hướng: Cạnh có hướng.
- Đồ thị đơn: Giữa hai đỉnh chỉ có tối đa một cạnh.
- Đồ thị đa: Giữa hai đỉnh có thể có nhiều cạnh.
- Đồ thị liên thông: Mọi cặp đỉnh đều có đường đi nối với nhau.
- Đồ thị rỗng: Không có cạnh nào.
- Đồ thị đầy đủ: Mỗi cặp đỉnh đều được nối với nhau bằng một cạnh.
Đồ thị đóng vai trò quan trọng trong nhiều loại ứng dụng, chẳng hạn:
- Trong hệ thống điện thoại, chúng ta cần “chọn” kết nối có nguy cơ tắc nghẽn thấp
nhất trong nhiều kết nối cho trước giữa 2 tổng đài chuyển mạch.
- Xác định xem có hay không một liên kết từ trang web này tới trang web khác trong
một hệ thống web.
- Trong lĩnh vực giao thông, tìm đường đi ngắn nhất giữa 2 thành phố.
- Xác định tua du lịch “rẻ” nhất thăm quan tất cả các thành phố cho trước.
- Xác định thứ tự các học phần trong một chương trình đào tạo.

6
B. Biểu diễn đồ thị và Phương pháp ma trận kề
1. Danh sách kề
Khái niệm: Danh sách kề là một cách để lưu trữ đồ thị, trong đó mỗi đỉnh của đồ
thị lưu trữ một danh sách các đỉnh kề với nó.
Ví dụ cụ thể:
Giả sử chúng ta có đồ thị vô hướng sau:
Biểu diễn bằng danh sách kề:

2. Ma trận kề
Khái niệm: Ma trận kề là một ma trận vuông n x n, với n là số đỉnh trong đồ thị.
Nếu đỉnh i và j kề nhau, phần tử a[i][j] trong ma trận có giá trị là 1, ngược lại giá
trị là 0.
Các đỉnh: A, B, C, D (số thứ tự tương ứng: 0, 1, 2, 3)
Biểu diễn bằng ma trận kề:
A B C D
A [0, 1, 0, 1]
B [0, 0, 1, 0]
C [0, 0, 0, 1]
D [0, 0, 0, 0]
3. Lợi ích và hạn chế của từng phương pháp
- Danh sách kề:
o Lợi ích:
 Tiết kiệm bộ nhớ hơn cho đồ thị thưa (sparse graph).
 Thêm và xóa cạnh dễ dàng hơn.
o Hạn chế:
 Truy cập trực tiếp thông tin về cạnh giữa hai đỉnh chậm hơn so với
ma trận kề.
- Ma trận kề:
o Lợi ích:
 Dễ dàng lưu trữ và truy cập thông tin về các cạnh trong đồ thị.
 Hiệu quả cho các thuật toán đồ thị liên quan đến ma trận (như tìm
đường đi ngắn nhất).
o Hạn chế:
 Tốn nhiều bộ nhớ hơn cho đồ thị thưa, vì cần không gian lưu trữ là
O(n^2).
 Thêm và xóa cạnh ít linh hoạt hơn.

7
Dựa vào ưu điểm và nhược điểm của 2 phương pháp, ta chọn biểu diễn ma trận kề.
1. Khai báo và nhập số đỉnh:
’soDinh’: Biến để lưu
số đỉnh của đồ thị.
2. Khởi tạo ma trận kề:

‘maTranKe’: biểu diễn dưới dạng một vector hai chiều, có kích thước ‘soDinh x
soDinh’.
3. Nhập ma trận: Sử dụng vòng lặp để nhập từng phần tử hàng i cột j.
4. In ma trận kiểm tra code: Sử dụng vòng lặp để in từng phần tử
của ma trận kề.

INPUT : OUTPUT:

C. Tính liên thông và kiểm tra tính liên thông


Khái niệm:
- Đồ thị liên thông: Mọi cặp đỉnh đều có đường đi nối với nhau.
- Thành phần liên thông: Tập con lớn nhất của đồ thị sao cho mọi cặp đỉnh trong tập con
đó đều có đường đi nối với nhau.
Thuật toán kiểm tra tính liên thông:
- Thuật toán DFS (Depth-First Search): Duyệt qua đồ thị theo chiều sâu, đánh dấu các
đỉnh đã duyệt.
- Thuật toán BFS (Breadth-First Search): Duyệt qua đồ thị theo chiều rộng, đánh dấu các
đỉnh đã duyệt.
Ứng dụng:
- Xác định số lượng thành phần liên thông trong đồ thị.
- Kiểm tra xem hai đỉnh có được nối với nhau hay không.

8
Sơ đồ khối :

Khởi tạo Code kiểm tra tính liên thông dựa vào thuật toán chiều sâu:

- H
à
m

DFS (Depth-First Search) có tác dụng thực hiện việc duyệt qua tất cả các đỉnh của đồ
thị theo chiều sâu. Mục đích chính của hàm này trong ngữ cảnh kiểm tra tính liên thông
của đồ thị là để đánh dấu tất cả các đỉnh mà có thể truy cập được từ một đỉnh xuất phát.
Điều này giúp xác định xem tất cả các đỉnh trong đồ thị có được kết nối với nhau hay

không.
Hàm isConnected trong đoạn mã C++ có tác dụng kiểm tra xem đồ thị có liên thông hay
không. Tính liên thông của đồ thị có nghĩa là từ bất kỳ đỉnh nào, bạn có thể đi đến tất cả các
đỉnh khác thông qua các cạnh của đồ thị.
Cấu trúc và Chức năng của hàm isConnected
1. Khởi tạo số đỉnh và vector visited:
int numVertices = maTranKe.size();
9
vector<bool> visited(numVertices, false);
o numVertices được khởi tạo để lưu số đỉnh của đồ thị, lấy từ kích thước của ma
trận kề maTranKe.
o visited là một vector kiểu bool với kích thước bằng số đỉnh của đồ thị, được khởi
tạo với giá trị false. Vector này dùng để đánh dấu các đỉnh đã được thăm trong
quá trình duyệt đồ thị.
2. Duyệt đồ thị bắt đầu từ đỉnh 0 bằng DFS:
DFS(0, visited, maTranKe);
o Hàm DFS (Depth-First Search) được gọi với đỉnh bắt đầu là đỉnh 0. Hàm này sẽ
đánh dấu tất cả các đỉnh có thể truy cập được từ đỉnh 0 là đã thăm.
3. Kiểm tra tất cả các đỉnh đã được thăm hay chưa:
for (bool v : visited) {
if (!v) {
return false;
}
}
return true;
o Sau khi hoàn tất DFS, vòng lặp for sẽ kiểm tra tất cả các giá trị trong vector
visited.
o Nếu có bất kỳ giá trị nào trong visited là false, nghĩa là có ít nhất một đỉnh không
thể truy cập từ đỉnh 0, hàm sẽ trả về false, tức là đồ thị không liên thông.
o Nếu tất cả các giá trị trong visited đều là true, hàm sẽ trả về true, tức là đồ thị liên
thông.
Tóm tắt tác dụng của hàm isConnected
Hàm isConnected kiểm tra tính liên thông của một đồ thị bằng cách thực hiện các bước sau:
1. Khởi tạo vector visited để đánh dấu các đỉnh đã thăm.
2. Gọi hàm DFS bắt đầu từ đỉnh 0 để duyệt qua tất cả các đỉnh có thể truy cập từ đỉnh 0.
3. Kiểm tra vector visited để xem tất cả các đỉnh có được thăm hay không.
o Nếu tất cả các đỉnh đều được thăm, hàm trả về true (đồ thị liên thông).
o Nếu có bất kỳ đỉnh nào không được thăm, hàm trả về false (đồ thị không liên
thông).
Ví dụ minh họa

10
Giả sử bạn có một đồ thị với 4 đỉnh và ma trận kề như sau:
0100
1010
0101
0010
Đồ thị này có cấu trúc như sau:0 - 1 - 2 - 3
Khi gọi hàm isConnected với ma trận kề này:
a) Khởi tạo vector visited với các giá trị false: [false, false, false, false].
b) Gọi hàm DFS từ đỉnh 0:
o Đỉnh 0 được thăm, vector visited trở thành [true, false, false, false].
o Đỉnh 1 được thăm, vector visited trở thành [true, true, false, false].
o Đỉnh 2 được thăm, vector visited trở thành [true, true, true, false].
o Đỉnh 3 được thăm, vector visited trở thành [true, true, true, true].
c) Kiểm tra vector visited:
o Tất cả các giá trị đều là true, do đó hàm trả về true, tức là đồ thị liên thông.
Ngược lại, nếu có bất kỳ giá trị nào trong visited vẫn là false sau khi gọi DFS, hàm sẽ trả về
false, cho biết đồ thị không liên thông.

4. Hàm main
a) Sử dụng nhập ma trận kề ở Mục B(tr.9)
b) Thông báo ra màn hình tính liên thông

5. Input Output
Ví dụ đồ thị liên thông

11
Ví dụ đồ thị không liên thông

12
CHƯƠNG 2: TÌM KIẾM TRÊN ĐỒ THỊ - ĐỒ THỊ EULER VÀ ĐỒ THỊ HAMILTON
A. Đồ thị Euler
 Bài toán mở đầu:

- Có thể đi qua cả 7 cây cầu, mỗi cầu đúng một lần, rồi quay về vị trí xuất phát được hay
không?

- Bài toán đã làm say mê cư dân của thành phố. Họ háo hức đi thử nhưng không thành
công.

- Năm 1736, Leonhard Euler (nhà toán học Thụy Sĩ) đã chứng minh rằng bài toán không
giải được.

- Từ bài toán này dẫn đến các khái niệm về đường, chu trình Euler và đồ thị Euler.
I. Khái niệm
- Đường Euler là đường đi qua mỗi cạnh của đồ thị đúng một lần.
- Chu trình Euler là chu trình đi qua mỗi cạnh của đồ thị đúng một lần.
- Đồ thị Euler là đồ thị có chu trình Euler.
- Đồ thị nửa Euler là đồ thị có đường đi Euler.
II. Định lý-Hệ Quả
Định lý:
- Đồ thị vô hướng liên thông là Euler khi và chỉ khi mọi đỉnh đều có bậc chẵn.
- Đồ thị có hướng liên thông là Euler khi và chỉ khi với mọi đỉnh tổng bán bậc vào bằng
tổng bán bậc
ra của nó
(tức là mọi
đỉnh đều cân
bằng).

13
Hệ quả:
- Đồ thị vô hướng liên thông là nửa Euler khi và chỉ khi nó chứa không quá 2 đỉnh bậc lẻ.
- Đồ thị có hướng liên thông là nửa Euler khi và chỉ khi nó chứa 2 đỉnh a, b thoả mãn:
indeg(a) = outdeg(a) – 1 và indeg(b) = outdeg(b) + 1, còn các đỉnh khác đều cân bằng
III.

Thuật toán –Mã giải

 Chu trình Euler là một chu trình trong đồ thị đi qua mỗi cạnh đúng một lần và kết thúc
tại đỉnh xuất phát.
 Đường đi Euler là một đường đi trong đồ thị đi qua mỗi cạnh đúng một lần nhưng
không nhất thiết phải quay lại đỉnh xuất phát.
 Điều kiện để có chu trình Euler là tất cả các đỉnh của đồ thị phải có bậc chẵn.
 Điều kiện để có đường đi Euler là đồ thị phải có đúng hai đỉnh có bậc lẻ.

14
IV. Sơ đồ khối

V. Code , Input Output

 Tối ưu hàm isConnected


 Đảm bảo rằng thuật toán DFS bắt đầu từ một đỉnh có bậc > 0, giúp kiểm tra chính xác
tính liên thông của đồ thị.
 Tránh trường hợp bắt đầu từ một đỉnh cô lập (không có cạnh nào nối với nó), điều này sẽ
gây hiểu lầm về tính liên thông của đồ thị.

Kết quả chương trình:

 Input: Người dùng nhập số đỉnh của đồ thị và ma trận kề tương ứng.
 Output: Chương trình in ra một trong các thông báo sau:
o "Đồ thị có Chu trình Euler"
o "Đồ thị có Đường đi Euler"
o "Đồ thị không có Chu trình Euler và không có Đường đi Euler"
o "Đồ thị không liên thông"

15
16
17
VI. Tìm đường đi tối ưu Euler

Hàm findEulerianPath có mục đích chính là kiểm tra xem đồ thị đầu vào có tồn
tại đường đi Euler hay không.
Sử dụng thuật toán Hierholzer để tìm đường đi Euler. Thuật toán này đảm bảo
rằng chúng ta duyệt qua tất cả các cạnh của đồ thị đúng một lần và tìm được đường đi
Euler nếu nó tồn tại.

B.

18
Đồ thị Hamilton
I. Khái niệm
- Đường Hamilton là đường đi qua mỗi đỉnh của đồ thị đúng một lần.
- Chu trình Hamilton là chu trình đi qua mỗi đỉnh của đồ thị đúng một lần.
- Đồ thị Hamilton là đồ thị có chu trình Hamilton.
- Đồ thị nửa Hamilton là đồ thị có đường đi Hamilton.

Các ví dụ (2/2)
- Tổ chức tour du lịch sao cho người du lịch thăm quan mỗithắng cảnh trong thành phố
đúng một lần
- Bài toán mã đi tuần: cho con mã đi trên bàn cờ vua sao cho nó đi qua mỗi ô đúng một
lần.

Đường Hamilton biểu diễn nước đi của con mã


trên bàn cờ 3x4:

II. Định lý-Nhận xét


- Định lý Dirac
Nếu mọi a thuộc V, deg(a) >= (n/2) thì đồ thị vô hướng G(V,E) cóchu trình Hamilton.
- Nhận xét
1. Đồ thị có đỉnh bậc ≤ 1 thì không có chu trình Hamilton.
2. Nếu đồ thị có các đỉnh đều có bậc 2 và có một đỉnh bậc 2 thì mọi chu trình Hamilton (nếu
có) phải đi qua 2 cạnh kề của đỉnh này.
3. Nếu trong đồ thị có một đỉnh kề với 3 đỉnh bậc 2 thì không có chu trình Hamilton.
19
III. Thuật Toán Hamilton
1. Khởi tạo:
a. Tạo một mảng path để lưu trữ đường đi Hamilton hiện tại.
b. Khởi tạo tất cả các giá trị trong path là -1.
c. Bắt đầu từ đỉnh 0: path[0] = 0.
2. Đệ quy:
a. Bắt đầu từ đỉnh hiện tại trong path, thử tất cả các đỉnh tiếp theo có thể.
b. Kiểm tra xem đỉnh tiếp theo có thể thêm vào đường đi hiện tại không (đỉnh này
chưa được thăm và có cạnh nối từ đỉnh hiện tại đến đỉnh tiếp theo).
c. Nếu đỉnh tiếp theo hợp lệ, thêm nó vào path và tiếp tục đệ quy với đỉnh này.
d. Nếu thêm được tất cả các đỉnh, kiểm tra xem đỉnh cuối cùng có cạnh nối với đỉnh
đầu tiên không. Nếu có, đã tìm được chu trình Hamilton.
3. Quay lui:
a. Nếu không thể thêm đỉnh tiếp theo vào path, loại bỏ đỉnh cuối cùng và thử đỉnh
khác.
IV. Sơ đồ khối

Giải thích sơ đồ khối

1. Bắt đầu chương trình: Khởi động chương trình.


2. Nhập số đỉnh: Nhập số lượng đỉnh của đồ thị từ người dùng.
3. Khởi tạo ma trận kề: Tạo ma trận kề với kích thước soDinh x soDinh và giá trị ban đầu là 0.
4. Nhập ma trận kề: Nhập các giá trị của ma trận kề từ người dùng.
5. Kiểm tra tính liên thông: Gọi hàm kiemTraLienThong để kiểm tra tính liên thông của đồ thị.
o Nếu đồ thị không liên thông, in thông báo và kết thúc chương trình.
o Nếu đồ thị liên thông, tiếp tục với bước tiếp theo.
6. Tìm đường đi Hamilton: Khởi tạo vector đánh dấu các đỉnh đã thăm và gọi hàm
timDuongDiHamilton để tìm đường đi Hamilton bắt đầu từ đỉnh 0.
o Nếu tìm thấy đường đi Hamilton, in đường đi và thông báo.
o Nếu không tìm thấy, in thông báo không có đường đi Hamilton.
7. Kết thúc chương trình: Kết thúc chương trình

20
21
V.
C

22
ode, Input –Output

Giải thích code và chú thích:

 DFS: Hàm để kiểm tra tính liên thông của đồ thị bằng cách đánh dấu các đỉnh đã thăm.
 kiemTraLienThong: Hàm kiểm tra xem đồ thị có liên thông hay không, trừ các đỉnh
cô lập.
 timDuongDiHamilton: Hàm sử dụng thuật toán quay lui (backtracking) để tìm đường
đi Hamilton từ một đỉnh đến đỉnh khác.
 kiemTraHamilton: Hàm kiểm tra xem đồ thị có phải là đồ thị Hamilton hay không và
nếu có, tìm một đường đi Hamilton.
 main: Nhập ma trận kề của đồ thị từ người dùng, kiểm tra loại đồ thị Hamilton và nếu
có, tìm và in ra một đường đi Hamilton.
C. Ưu và Nhược điểm, so sánh 2 thuật toán Euler và Hamilton
- Thuật toán Euler
Ưu điểm:
o Đơn giản và hiệu quả: Thuật toán tìm đường đi Euler (hoặc chu trình Euler) khá
đơn giản trong việc kiểm tra và tìm kiếm, đặc biệt là khi chỉ cần duyệt qua mỗi
cạnh một lần.
o Độ phức tạp thấp: Thời gian thực thi của thuật toán Euler thường nhỏ hơn so với
thuật toán Hamilton vì không cần kiểm tra tất cả các hoán vị của đỉnh.
o Ứng dụng rộng rãi: Có thể áp dụng trong nhiều lĩnh vực thực tế như mạng lưới
điện, mạng lưới giao thông, lập lịch công việc,...
Nhược điểm:
o Yêu cầu đồ thị liên thông: Chỉ áp dụng được trên đồ thị liên thông. Điều này là
hạn chế lớn vì nếu đồ thị không liên thông, không thể tạo được chu trình hoặc
đường đi Euler.
o Giới hạn về bậc của đỉnh: Yêu cầu đồ thị có số đỉnh bậc lẻ là 0 hoặc 2 để có thể
tạo được chu trình hoặc đường đi Euler.
- Thuật toán Hamilton
Ưu điểm:
o Tính tổng quát cao: Thuật toán Hamilton có thể tìm kiếm tất cả các đường đi qua
mỗi đỉnh một lần, vì vậy nó có thể áp dụng được trên mọi loại đồ thị.
o Kiểm tra tất cả các đỉnh: Thuật toán Hamilton có thể tìm tất cả các chu trình
Hamilton hoặc các đường đi Hamilton có thể có trong đồ thị.
o Độ chính xác cao: Nếu tìm thấy, thuật toán Hamilton sẽ cho kết quả chính xác mà
không cần điều kiện đặc biệt như yêu cầu của Euler.
Nhược điểm:
o Độ phức tạp cao: So với thuật toán Euler, thuật toán Hamilton có độ phức tạp tính
toán cao hơn, đặc biệt là khi đồ thị có số lượng đỉnh lớn.
o Khó khăn trong tìm kiếm: Tìm kiếm chu trình hoặc đường đi Hamilton có thể mất
nhiều thời gian và tài nguyên tính toán.
- So sánh:
o Độ phức tạp: Euler thường nhanh hơn Hamilton vì không cần phải kiểm tra tất cả
các hoán vị của các đỉnh.
o Định lý: Euler yêu cầu đồ thị liên thông và số đỉnh bậc lẻ là 0 hoặc 2, trong khi
23
Hamilton có thể áp dụng trên mọi loại đồ thị.
o Tính tổng quát: Hamilton có tính tổng quát cao hơn và có thể tìm kiếm tất cả các
chu trình hoặc đường đi Hamilton có thể có.
CHƯƠNG 3: CÂY VÀ KHUNG CỰC TIỂU CỦA ĐỒ THỊ

A. Thuật toán Prim

I. Khái niệm
Bài toán cây khung cực tiểu
Các bài toán đặt ra:
 Làm sao xây dựng mạng giao thông nối các thành phố với chi phí xây dựng và vận
hành thấp nhất?
 Trong lý thuyết mạch, làm thế nào để xây dựng một mạch điện tử có kích thước, chi
phí thấp nhất và tốc độ truyền tín hiệu nhanh nhất?
 Trong mạng máy tính, đòi hỏi xây dựng hệ thống mạng có chi phí kết nối thấp nhất và
tốc độ truyền dữ liệu cao nhất ?
Ví dụ:

Các
định nghĩa:
- Cây là đơn đồ thị liên thông và không có chu trình
- Cây khung:
+ Giả sử G(V,E) là đồ thị vô hướng liên thông, khi đó:
24
+

Cây dung T(V,E’) của G là đồ thị con của G, sao cho:


• T liên thông
• và không có chu trình.
+ Tức là E’ là tập con của E.

Thuật toán Prim là một thuật toán trong đồ thị để tìm ra cây khung nhỏ nhất (Minimum
Spanning Tree - MST). MST của một đồ thị là một cây con của đồ thị đó, bao gồm tất cả các
đỉnh của đồ thị và một số cạnh sao cho tổng trọng số của các cạnh đó là nhỏ nhất có thể.
II. Điều kiện tồn tại
 Đồ thị phải là một đồ thị liên thông để có thể có MST.
 Các cạnh trong đồ thị có trọng số không âm.
III. Thuật toán (mã giải)
 Bước 1:
- Khởi tạo từ 1 đỉnh bất kỳ, nạp đỉnh đó vào MST rỗng.
 Bước 2:
- Lặp lại đến khi mọi đỉnh của G đều được nạp vào MST:
• Tìm tất cả các cạnh nối đỉnh mới nhất trong MST với các đỉnh không thuộc MST, và
đặt vào 1 hàng đợi (ưu tiên). Nếu có nhiều hơn 1 cạnh nối với cùng đỉnh đích thì chọn
cạnh có trọng số nhỏ nhất.
• Chọn cạnh có trọng số nhỏ nhất trong hàng đợi, và bổ sung cạnh này cùng với đỉnh
đích tương ứng vào MST.
IV. Sơ đồ khối

25
Sơ đồ khối này thể hiện chi tiết quá trình thực hiện thuật toán Prim từ khởi tạo
đến khi tìm được cây khung nhỏ nhất của đồ thị.
V. Code, Input/Output
Chỉnh sửa sơ bộ cách nhập vào ma trận kề có thêm trọng số :

26
- Kiểm tra tính liên thông của đồ thị (Hàm DFS và kiemTraLienThong):
o Hàm DFS (Duyệt theo chiều sâu): Duyệt từ một đỉnh, đánh dấu tất cả các đỉnh có
thể đến được từ đỉnh đó.
o Hàm kiemTraLienThong:
 Tìm đỉnh đầu tiên có cạnh nối (bậc > 0).
 Sử dụng DFS để kiểm tra xem tất cả các đỉnh có bậc > 0 đều có thể đến
được từ đỉnh đầu tiên.
 Nếu tất cả các đỉnh có bậc > 0 đều được thăm, đồ thị liên thông; ngược lại,
không liên thông.
- Tìm cây khung nhỏ nhất (MST) bằng thuật toán Prim (Hàm primMST):
o Khởi tạo:
 key[]: Lưu trọng số nhỏ nhất để thêm một đỉnh vào MST.
 parent[]: Lưu chỉ số của đỉnh cha trong MST.
 trongMST[]: Đánh dấu các đỉnh đã thuộc MST.
o Thuật toán Prim:
 Bắt đầu từ đỉnh 0, đặt key[0] = 0 và parent[0] = -1.
 Lặp lại soDinh - 1 lần để thêm từng đỉnh vào MST.
 Trong mỗi lần lặp, tìm đỉnh u có key nhỏ nhất chưa nằm trong MST và
đưa u vào MST.
 Cập nhật key và parent của các đỉnh kề với u nếu trọng số cạnh u-v nhỏ
hơn key[v].
- In kết quả: In ra các cạnh của MST và trọng số tương ứng.
 Chương trình chính (main):
o Nhập số đỉnh và ma trận kề có trọng số của đồ thị.
o Kiểm tra tính liên thông của đồ thị bằng hàm kiemTraLienThong.
o Nếu đồ thị liên thông, gọi hàm primMST để tìm cây khung nhỏ nhất và in kết
quả.
o Nếu đồ thị không liên thông, thông báo không thể tìm cây khung nhỏ nhất.
Input-Outut:

27
B. Thuật toán Kruskal
I. Khái niệm
- Thuật toán Kruskal là một thuật toán nổi tiếng để tìm cây khung nhỏ nhất (MST) của
một đồ thị liên thông, vô hướng và có trọng số. Thuật toán này thuộc nhóm thuật toán
tham lam (greedy algorithm), được đặt theo tên của Joseph Kruskal, người đã đề xuất nó
vào năm 1956.

II. Điều kiện tồn tại


 Đồ thị phải là đồ thị liên thông.
 Đồ thị có thể có hoặc không có chu trình.
 Mỗi cạnh của đồ thị phải có trọng số không âm.
III. Thuật toán

- Chọn cạnh
o Làm thế nào để biết việc bổ sung cạnh (u,v) vào cây T có tạo ra chu trình hay
không?
- Giải pháp gán nhãn (make-set)
o Nhãn là một số nguyên được gán cho các đỉnh.
o Các đỉnh thuộc cùng thành phần liên thông trong T sẽ có cùng nhãn.
o Mỗi thành phần liên thông của T có 1 nhãn khác nhau.
Trong thuật toán này ta sử dụng danh sách
cạch để nhập dữ liệu vào để dể dàng thao
tác :

28
IV. Sơ đồ khối

Giải thích sơ đồ khối:

1. Bắt đầu: Bắt đầu quá trình thực thi của thuật toán.
2. Nhập số đỉnh của đồ thị và số cạnh: Người dùng nhập số đỉnh và số cạnh của đồ thị.
3. Khởi tạo danh sách cạnh E: Tạo một danh sách để lưu trữ các cạnh của đồ thị.
4. Đọc và lưu các cạnh vào danh sách E: Đọc từng cạnh từ người dùng và lưu vào danh
sách cạnh E.
5. Sắp xếp danh sách E theo trọng số cạnh tăng dần: Sắp xếp danh sách các cạnh theo
trọng số từ nhỏ đến lớn để thuật toán có thể xử lý từng cạnh theo thứ tự.
6. Khởi tạo cây khung T rỗng: Khởi tạo một danh sách để lưu trữ các cạnh của cây khung
nhỏ nhất (MST).
7. Khởi tạo cấu trúc Union-Find để quản lý các tập con: Sử dụng cấu trúc Union-Find
để theo dõi và quản lý các tập con của các đỉnh, giúp xác định liệu việc thêm cạnh có tạo
chu trình hay không.
8. Vòng lặp cho đến khi cây khung T có đủ (V - 1) cạnh hoặc E rỗng: Lặp để chọn các
cạnh vào cây khung nhỏ nhất. Vòng lặp dừng khi cây khung T có đủ số cạnh là (V - 1)
hoặc danh sách các cạnh E đã được duyệt hết.
9. Lấy cạnh có trọng số nhỏ nhất từ danh sách E: Chọn cạnh có trọng số nhỏ nhất từ
danh sách cạnh đã sắp xếp.
10. Nếu cạnh (u, v) không tạo thành chu trình khi thêm vào cây khung T: Kiểm tra xem
việc thêm cạnh (u, v) vào cây khung T có tạo ra chu trình hay không bằng cấu trúc
Union-Find. Nếu không tạo chu trình, thêm cạnh vào cây khung T.
11. Nếu số cạnh của cây khung T là (V - 1): Nếu cây khung T đã có đủ (V - 1) cạnh, xuất
cây khung T và tổng trọng số của nó.
12. Ngược lại: Nếu không đủ số cạnh, xuất thông báo không tìm được cây khung nhỏ nhất.
13. Kết thúc: Kết thúc quá trình thực thi của thuật toán.

Đây là quy trình chi tiết của thuật toán Kruskal, mô tả các bước từ nhập dữ liệu, xử lý, cho đến
xuất kết quả.

29
30
V. Code, Input/Output

31
32
struct Edge: Lưu trữ thông tin về các cạnh của đồ thị với ba thuộc tính: u (đỉnh bắt đầu), v
(đỉnh kết thúc) và weight (trọng số của cạnh). Toán tử < được định nghĩa để hỗ trợ sắp xếp các
cạnh theo trọng số tăng dần.
findSet: Hàm tìm tập hợp của một đỉnh sử dụng kỹ thuật "path compression" trong Union-Find
để tăng hiệu quả.
unionSets: Hàm hợp nhất hai tập hợp sử dụng kỹ thuật "union by rank" trong Union-Find để
giữ cho cây đại diện nhỏ nhất có thể.
DFS: Hàm thực hiện duyệt đồ thị bằng thuật toán DFS để kiểm tra tính liên thông của đồ thị.
kiemTraLienThong: Kiểm tra đồ thị có liên thông hay không bằng cách duyệt tất cả các đỉnh
có cạnh kết nối. Nếu tất cả các đỉnh có bậc lớn hơn 0 đều được thăm thì đồ thị liên thông.
kruskalMST: Tìm cây khung nhỏ nhất bằng cách:
o Sắp xếp các cạnh theo trọng số tăng dần.
o Khởi tạo cấu trúc Union-Find.
o Duyệt qua các cạnh, thêm các cạnh vào cây khung nếu việc thêm không tạo thành
chu trình (kiểm tra bằng Union-Find).
o In các cạnh của cây khung nhỏ nhất và tổng trọng số.
Main:
 Nhập số đỉnh và số cạnh của đồ thị.
 Nhập các cạnh và trọng số tương ứng, lưu vào ma trận kề và danh sách các cạnh.
 Kiểm tra tính liên thông của đồ thị. Nếu đồ thị liên thông, thực hiện thuật toán Kruskal để
tìm cây khung nhỏ nhất. Nếu không, thông báo đồ thị không liên thông và không thể tìm cây
khung nhỏ nhất.
INPUT-OUTPUT

33
C. Ưu và Nhược điểm của Thuật toán Prim và Kruskal
Thuật toán Prim
- Ưu điểm:
1. Hiệu quả với đồ thị đậm đặc: Thuật toán Prim hoạt động tốt trên các đồ thị đậm đặc, nơi
mà số lượng cạnh lớn (gần bằng số cạnh tối đa có thể).
2. Dễ hiểu và triển khai: Đặc biệt khi sử dụng cấu trúc dữ liệu như hàng đợi ưu tiên, thuật
toán Prim dễ hiểu và triển khai.
- Nhược điểm:
1. Phụ thuộc vào lựa chọn đỉnh ban đầu: Kết quả của thuật toán Prim có thể phụ thuộc vào
đỉnh khởi đầu.
2. Không phù hợp cho đồ thị thưa: Khi số lượng cạnh ít, hiệu quả của thuật toán Prim
giảm, đặc biệt là khi sử dụng ma trận kề.
Thuật toán Kruskal
- Ưu điểm:
1. Hiệu quả với đồ thị thưa: Thuật toán Kruskal hoạt động tốt trên các đồ thị thưa, nơi mà
số lượng cạnh nhỏ so với số lượng đỉnh.
2. Không phụ thuộc vào lựa chọn đỉnh ban đầu: Thuật toán Kruskal không phụ thuộc vào
đỉnh khởi đầu, do đó kết quả là duy nhất với cùng một tập cạnh và trọng số.
- Nhược điểm:
1. Cần sắp xếp cạnh: Quá trình sắp xếp các cạnh theo trọng số tốn thêm thời gian và có thể
trở thành nút cổ chai cho hiệu suất của thuật toán.
2. Cần kiểm tra chu trình: Quá trình kiểm tra và hợp nhất các tập hợp (để đảm bảo không
tạo chu trình) có thể phức tạp và tốn kém nếu không sử dụng cấu trúc dữ liệu Union-
Find hiệu quả.
So sánh Thuật toán Prim và Kruskal
- Prim: Bắt đầu từ một đỉnh và mở rộng MST bằng cách thêm dần các cạnh nhỏ nhất kết
nối đến các đỉnh chưa nằm trong MST.
- Kruskal: Bắt đầu bằng cách sắp xếp tất cả các cạnh, sau đó thêm dần các cạnh nhỏ nhất
vào MST, đảm bảo không tạo thành chu trình.
o Prim: Hiệu quả hơn với đồ thị đậm đặc.
o Kruskal: Hiệu quả hơn với đồ thị thưa.
Độ phức tạp:
- Prim: Sử dụng hàng đợi ưu tiên (heap) có độ phức tạp là O(E + V log V) với E là số
cạnh và V là số đỉnh.
- Kruskal: Sử dụng Union-Find để kiểm tra và hợp nhất các tập hợp, có độ phức tạp là
O(E log E) hoặc O(E log V) sau khi sắp xếp các cạnh.
Yêu cầu cấu trúc dữ liệu:
- Prim: Yêu cầu hàng đợi ưu tiên và ma trận kề hoặc danh sách kề.
- Kruskal: Yêu cầu danh sách cạnh và cấu trúc dữ liệu Union-Find.
- Prim: Phụ thuộc vào lựa chọn đỉnh ban đầu.
- Kruskal:Không phụ thuộc vào lựa chọn đỉnh ban đầu, chỉ phụ thuộc vào trọng số củacác
cạnh.
Kết luận
- Thuật toán Prim thích hợp hơn cho đồ thị đậm đặc và khi có thể dễ dàng sử dụng hàng
đợi ưu tiên.
- Thuật toán Kruskal thích hợp hơn cho đồ thị thưa và khi cần một cách tiếp cận đơn giản
hơn để kiểm tra các cạnh mà không phụ thuộc vào đỉnh ban đầu.
34
CHƯƠNG 4: TÌM ĐƯỜNG ĐI NGẮN NHẤT
A. Bài toán đường đi ngắn nhất

35
36
I. Khái niệm
Thuật toán Dijkstra là một thuật toán được sử dụng để tìm đường đi ngắn nhất từ một
đỉnh nguồn đến tất cả các đỉnh khác trong một đồ thị có trọng số không âm.

II. Điều Kiện Tồn Tại

1. Đồ thị có trọng số không âm: Thuật toán Dijkstra không hoạt động đúng khi đồ thị có
cạnh với trọng số âm.
2. Đồ thị liên thông: Mặc dù không bắt buộc, nhưng để tìm đường đi ngắn nhất đến tất cả
các đỉnh, đồ thị nên liên thông.

III. Thuật Toán (Mã Giải)


 Đặc điểm:
 Chỉ áp dụng với đồ thị có trọng số không âm.
 Tìm đường đi ngắn nhất từ 1 đỉnh xuất phát đến mọi đỉnh còn lại của đồ thị.
 Ý tưởng: sử dụng nguyên lý tham lam (greedy)
 Tại mỗi bước luôn chọn đường đi ngắn nhất có thể.
 Đường đi ngắn nhất tới đỉnh chưa xét được xây dựng từ đường đi ngắn nhất qua các
đỉnh đã được xét.

- Dijkstra(V,E,C,s){
 Với mỗi đỉnh v thuộc V gán:
 distance(v) = vô cùng; previous(v) = s;
 Distance(s)=0; Queue = V \ {s}; SP = s;
 While(Queue khác rỗng){
- Lấy x là đỉnh có distance(x) = Min {distance(Queue)}
- Nạp x vào SP
- Với mỗi đỉnh y thuộc Queue và kề với x,
- nếu distance(y) < distance(x)+c(x,y){
o Cập nhật distance(y) = distance(x)+c(x,y);
o Cập nhật previous(y) = x;
}
}
Return SP;
}
Phân tích thuật toán

 Khởi tạo:

 Với mỗi đỉnh vvv thuộc VVV:


o distance(v) = vô cùng (INT_MAX).
o previous(v) = s (đỉnh nguồn).
 distance(s) = 0 (khoảng cách từ đỉnh nguồn đến chính nó).
 Queue = V \ {s} (tập hợp các đỉnh chưa được xét).
 SP = s (tập hợp các đỉnh đã được xét).

 Vòng lặp chính:

37
 Trong khi Queue chưa rỗng:
o Lấy đỉnh xxx có distance(x) nhỏ nhất từ Queue.
o Đưa xxx vào SP.
o Với mỗi đỉnh yyy thuộc Queue và kề với xxx:
 Nếu distance(y) > distance(x) + c(x, y) (trọng số cạnh từ xxx đến yyy):
 Cập nhật distance(y) = distance(x) + c(x, y).
 Cập nhật previous(y) = x.

 Kết thúc:

 Trả về tập hợp các đỉnh đã xét (SP).

IV. Sơ đồ khối

Giải thích sơ đồ khối:

1. Bắt đầu:
o Bước đầu tiên là nhập số đỉnh và số cạnh của đồ thị.
o Tiếp theo, nhập các cạnh và trọng số tương ứng.
2. Kiểm tra tính liên thông:
o Kiểm tra xem đồ thị có liên thông hay không. Nếu không, in ra thông báo và kết thúc
chương trình.
3. Đồ thị liên thông:
o Nếu đồ thị là liên thông, tiếp tục chương trình bằng việc chọn đỉnh nguồn và khởi tạo
các biến cần thiết như khoảng cách và hàng đợi ưu tiên.
4. Lặp cho đến khi hàng đợi rỗng:
o Trong mỗi vòng lặp, lấy ra đỉnh u có khoảng cách nhỏ nhất từ hàng đợi.
o Duyệt qua các đỉnh kề của u để cập nhật khoảng cách và đỉnh trước đó nếu tìm được
đường đi ngắn hơn.
5. Cập nhật khoảng cách và đỉnh trước đó:
o Nếu tìm được đường đi ngắn hơn đến đỉnh kề, cập nhật khoảng cách và đỉnh trước đó
của đỉnh kề.
o Đưa đỉnh kề vào hàng đợi ưu tiên để xử lý tiếp.
6. Kết thúc:
o Sau khi xử lý hết các đỉnh trong hàng đợi, in ra khoảng cách từ đỉnh nguồn đến các đỉnh
khác và đường đi chi tiết từ đỉnh nguồn.

Sơ đồ khối này giúp mô tả một cách trực quan quy trình hoạt động của thuật toán Dijkstra từ đầu vào
cho đến đầu ra, giúp hiểu rõ hơn về các bước và các bước điều kiện trong quá trình thực thi thuật toán.

38
V. Code, Input/Output

- Khởi tạo:

Nhập số đỉnh (soDinh) và số cạnh (soCanh) của đồ thị.

Nhập các cạnh của đồ thị với các giá trị: đỉnh đầu (u), đỉnh cuối (v), và trọng số (trongSo). Các cạnh
được lưu trữ vào danh sách kề (doThi) và ma trận kề (maTranKe).
 vector<int> truoc(soDinh, -1); được sử dụng để lưu trữ đỉnh trước đó trong đường đi ngắn nhất đến mỗi
đỉnh.
- Kiểm tra tính liên thông:
 Sử dụng hàm kiemTraLienThong để kiểm tra xem đồ thị có liên thông hay không.
 Hàm này sử dụng thuật toán DFS để duyệt qua tất cả các đỉnh có cạnh kề và đánh dấu chúng là đã
thăm.
39
- Thuật toán Dijkstra:
 Sử dụng hàng đợi ưu tiên (min-heap) để luôn chọn đỉnh có khoảng cách nhỏ nhất hiện tại.
 Cập nhật khoảng cách đến các đỉnh kề nếu tìm được đường đi ngắn hơn.
- In kết quả:
 In ra khoảng cách ngắn nhất từ đỉnh nguồn (dinhNguon) đến các đỉnh khác trong đồ thị.
 Sau khi tính toán khoảng cách, chương trình sẽ in khoảng cách và đường đi từ đỉnh nguồn đến từng
đỉnh khác.

- Tóm tắt:
Thuật toán Dijkstra dùng để tìm đường đi ngắn nhất từ một đỉnh nguồn đến tất cả các đỉnh còn
lại trong đồ thị có trọng số không âm.
Sử dụng hàng đợi ưu tiên (min-heap) để lấy đỉnh có khoảng cách nhỏ nhất.
Cập nhật khoảng cách và đỉnh trước đó khi tìm được đường đi ngắn hơn.
Kết quả được in ra bao gồm khoảng cách và đường đi chi tiết từ đỉnh nguồn đến mỗi đỉnh khác
40
trong đồ thị.
C. Thuật toán Bellman – Ford
I. Khái niệm
- Thuật toán Bellman-Ford là một thuật toán dùng để tìm đường đi ngắn nhất từ một đỉnh
đến tất cả các đỉnh còn lại trong đồ thị có hướng và có thể có cạnh có trọng số âm. Nếu
đồ thị chứa chu trình âm, thuật toán cũng phát hiện và báo cáo lỗi này.

II. Điều kiện tồn tại

Để áp dụng thuật toán Bellman-Ford:

 Đồ thị phải là đồ thị có hướng và có thể có cạnh có trọng số âm.


 Các cạnh và đỉnh của đồ thị phải được biểu diễn một cách hợp lệ theo định dạng đầu vào của
thuật toán.

III. Thuật toán (mã giải)

41
IV. Sơ đồ khối

Sơ đồ khối thuật toán Bellman-Ford

1. Bắt đầu (Start)


o Khởi động chương trình và chuẩn bị nhận đầu vào từ người dùng.
2. Nhập số đỉnh và số cạnh của đồ thị
o Nhận số đỉnh (V) và số cạnh (E) của đồ thị.
3. Nhập danh sách các cạnh (u, v, trọng số)
o Nhận danh sách các cạnh của đồ thị. Mỗi cạnh được biểu diễn bởi một cặp đỉnh (u, v) và
trọng số của cạnh đó.
4. Nhập đỉnh xuất phát
o Nhận đỉnh xuất phát (source) từ người dùng.
5. Kiểm tra tính liên thông của đồ thị
o Sử dụng thuật toán DFS để kiểm tra xem đồ thị có liên thông không. Đồ thị liên thông là
đồ thị mà từ bất kỳ đỉnh nào cũng có thể đi tới bất kỳ đỉnh nào khác.
o Nếu đồ thị không liên thông:
 In thông báo "Đồ thị không liên thông" và kết thúc chương trình.
o Nếu đồ thị liên thông:
 Tiếp tục các bước tiếp theo.
6. Khởi tạo khoảng cách và đỉnh trước đó
o Đặt khoảng cách từ đỉnh xuất phát đến chính nó là 0.

42
o Đặt khoảng cách đến các đỉnh khác là vô cùng (∞).
o Đặt đỉnh trước đó của tất cả các đỉnh là -1.
7. Thực hiện relax các cạnh (V - 1) lần
o Với mỗi cạnh (u, v) trong đồ thị, cập nhật khoảng cách và đỉnh trước đó nếu tìm thấy
đường đi ngắn hơn.
8. Kiểm tra chu trình âm
o Kiểm tra lại tất cả các cạnh. Nếu tìm thấy một cạnh mà khoảng cách đến đỉnh đích có
thể được cập nhật nhỏ hơn, tức là có chu trình âm.
o Nếu có chu trình âm:
 In thông báo "Đồ thị chứa chu trình âm" và kết thúc chương trình.
o Nếu không có chu trình âm:
 Tiếp tục bước tiếp theo.
9. In kết quả đường đi ngắn nhất từ đỉnh xuất phát đến tất cả các đỉnh còn lại
o In khoảng cách ngắn nhất từ đỉnh xuất phát đến mỗi đỉnh khác và đỉnh trước đó trên
đường đi ngắn nhất.
10. Kết thúc (End)
o Kết thúc chương trình.

V. Code, Input/Output

Cấu trúc Canh:

 u: Đỉnh đầu của cạnh.


 v: Đỉnh cuối của cạnh.
 trongSo: Trọng số của cạnh.

43
44
D. Ưu và Nhược điểm, So sánh hai thuật toán

Ưu và Nhược điểm của Thuật toán Bellman-Ford

Ưu điểm:

1. Xử lý trọng số âm: Thuật toán Bellman-Ford có thể xử lý các đồ thị có cạnh với trọng
số âm. Đây là điểm mạnh nhất của thuật toán này so với thuật toán Dijkstra.
2. Phát hiện chu trình âm: Thuật toán này có khả năng phát hiện chu trình âm trong đồ
thị, điều mà Dijkstra không thể làm được.
3. Đơn giản và dễ hiểu: Thuật toán khá đơn giản và dễ hiểu, dễ dàng được triển khai và
kiểm chứng.

Nhược điểm:

1. Thời gian thực hiện lâu: Thuật toán Bellman-Ford có độ phức tạp thời gian là
O(V⋅E)O(V \cdot E)O(V⋅E), nơi VVV là số đỉnh và EEE là số cạnh. Điều này khiến
thuật toán không phù hợp cho các đồ thị lớn.
2. Hiệu suất thấp: So với thuật toán Dijkstra (đặc biệt là với cấu trúc dữ liệu heap),
Bellman-Ford thường chậm hơn nhiều trên các đồ thị không có cạnh âm.

Ưu và Nhược điểm của Thuật toán Dijkstra

Ưu điểm:

1. Nhanh hơn trên đồ thị không có cạnh âm: Thuật toán Dijkstra có độ phức tạp thời
gian là O((V+E)logV)khi sử dụng hàng đợi ưu tiên (heap), giúp thuật toán này nhanh
hơn nhiều so với Bellman-Ford trên đồ thị không có cạnh âm.
2. Hiệu quả với các cấu trúc dữ liệu tiên tiến: Khi kết hợp với các cấu trúc dữ liệu như
Fibonacci heap, Dijkstra có thể đạt hiệu quả cao và rất nhanh trên các đồ thị lớn.

Nhược điểm:

1. Không xử lý được trọng số âm: Thuật toán Dijkstra không thể xử lý các đồ thị có cạnh
với trọng số âm, vì nó giả định rằng một khi đường đi ngắn nhất đến một đỉnh đã được
tìm thấy, đường đi đó không thể được cải thiện nữa.
2. Không phát hiện được chu trình âm: Thuật toán này không thể phát hiện chu trình âm
trong đồ thị.

So sánh hai thuật toán


45
Đặc điểm Thuật toán Bellman-Ford Thuật toán Dijkstra
Khả năng xử lý trọng số
Có thể xử lý trọng số âm Không thể xử lý trọng số âm
âm
Phát hiện chu trình âm Có thể phát hiện chu trình âm Không thể phát hiện chu trình âm
O((V+E)logV)(với hàng đợi ưu
Độ phức tạp thời gian O(V⋅E)
tiên)
Tốt cho đồ thị nhỏ hoặc có cạnh Tốt cho đồ thị lớn, không có cạnh
Ứng dụng
âm âm
Độ phức tạp Đơn giản, dễ hiểu Phức tạp hơn khi kết hợp với heap

Kết luận

 Bellman-Ford: Thích hợp cho các đồ thị có cạnh âm hoặc khi cần phát hiện chu trình
âm. Tuy nhiên, với độ phức tạp thời gian cao, thuật toán này không phù hợp cho các đồ
thị lớn.
 Dijkstra: Thích hợp cho các đồ thị lớn không có cạnh âm, hiệu quả và nhanh hơn nhiều
so với Bellman-Ford. Tuy nhiên, không thể xử lý các cạnh âm và không phát hiện được
chu trình âm.

46
PHẦN III: KẾT LUẬN

1. Thuật toán DFS (Duyệt theo chiều sâu)

Ưu điểm:

 Đơn giản, dễ triển khai.


 Phát hiện được thành phần liên thông của đồ thị.
 Tìm kiếm nhanh trên cấu trúc dữ liệu đồ thị.

Nhược điểm:

 Không phát hiện được đường đi ngắn nhất.


 Dễ bị rơi vào vòng lặp vô hạn trên đồ thị có chu trình.
 Không phát hiện được chu trình âm.

2. Thuật toán BFS (Duyệt theo chiều rộng)

Ưu điểm:

 Đơn giản và dễ triển khai.


 Tìm kiếm ngắn nhất trên đồ thị vô hướng và có thể được áp dụng trên đồ thị có trọng số không
âm.

Nhược điểm:

 Không phát hiện được đường đi ngắn nhất trên đồ thị có trọng số.
 Không phát hiện được chu trình âm.

3. Thuật toán Dijkstra

Ưu điểm:

 Tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn lại trên đồ thị có trọng số không
âm.
 Hiệu quả trên các đồ thị lớn khi sử dụng hàng đợi ưu tiên (heap).

Nhược điểm:

 Không thể xử lý đồ thị có trọng số âm.


 Độ phức tạp thời gian cao hơn khi so sánh với các thuật toán như Bellman-Ford trên đồ thị có
trọng số âm.

4. Thuật toán Bellman-Ford

Ưu điểm:

 Xử lý được đồ thị có cạnh có trọng số âm.


 Phát hiện được chu trình âm trong đồ thị.

Nhược điểm:
47
 Độ phức tạp thời gian lớn O(V⋅E)O(V \cdot E)O(V⋅E), không phù hợp cho các đồ thị lớn.
 Hiệu suất thấp hơn so với Dijkstra trên các đồ thị không có trọng số âm.

5. Thuật toán Floyd-Warshall

Ưu điểm:

 Tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh trên đồ thị có hướng hoặc vô hướng.
 Xử lý được đồ thị có cạnh có trọng số âm (nhưng không có chu trình âm).

Nhược điểm:

 Độ phức tạp thời gian O(V3)O(V^3)O(V3), không phù hợp cho các đồ thị lớn.
 Cần lưu ma trận khoảng cách O(V2)O(V^2)O(V2), tốn bộ nhớ.

6. Thuật toán Prim

Ưu điểm:

 Tìm cây bao trùm nhỏ nhất trên đồ thị vô hướng có trọng số.
 Hiệu quả với độ phức tạp thời gian O(Elog⁡V)O(E \log V)O(ElogV) khi sử dụng hàng đợi ưu
tiên.

Nhược điểm:

 Chỉ áp dụng được trên đồ thị vô hướng.


 Không xử lý được các đồ thị có chu trình hoặc đồ thị có hướng.

Kết luận

 Các thuật toán DFS và BFS phù hợp cho các tác vụ duyệt đồ thị và tìm kiếm đơn giản.
 Dijkstra và Bellman-Ford được sử dụng để tìm đường đi ngắn nhất, với Dijkstra phù hợp cho đồ
thị không có trọng số âm và Bellman-Ford cho cả hai trường hợp.
 Floyd-Warshall phù hợp để tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh.
 Prim dùng để tìm cây bao trùm nhỏ nhất trên đồ thị vô hướng có trọng số.

Mỗi thuật toán có ưu điểm và nhược điểm riêng, phù hợp với các bài toán cụ thể trong lĩnh vực lý
thuyết đồ thị và ứng dụng thực tế khác nhau.

48
TÀI LIỆU THAM KHẢO
Code
https://chatgpt.com/c/1e41c51d-daac-45a5-a08d-518b1763e2c0
Sơ đồ khối :
Dùng Paint+dữ kiện GPT
Tài liệu
Giáo trình học tập
https://courses.ut.edu.vn/pluginfile.php/1144014/mod_resource/content/2/Chuong5-
DoThiVaBieuDienDoThi.pdf

https://courses.ut.edu.vn/pluginfile.php/1144015/mod_resource/content/1/Chuong6-
%20TimKiemTrenDoThi-DTEuler-DTHamilton.pdf

https://courses.ut.edu.vn/pluginfile.php/1144016/mod_resource/content/1/Chuong7-
CayVaCayKhungCucTieu.pdf

https://courses.ut.edu.vn/pluginfile.php/1144017/mod_resource/content/1/Chuong
%208%20-%20TimDuongDiNganNhatVaLuongCDTrenMang.pdf

49

You might also like