Đặc biệt là các thuật toán trên đồ thị đã có nhiều ứng dụng trong nhiều lĩnh vực khác nhau như: Mạng máy tính, Lý thuyết mã, Tối ưu hoá, Kinh tế học v.v.... Bảy cây cầu trên sông Pregel
Trang 1LỜI CẢM ƠN
Để hoàn thành tốt được đề tài Nghiên cứu khoa học này là nhờ sự hướng dẫn và giúp đỡ của giảng viên Ts Hoàng Văn Dũng Em xin chân thành cảm ơn sự giúp đỡ của thầy
Em cũng rất cảm ơn các thầy cô trong khoa Kỹ thuật – Công nghệ thông tin trường Đại học Quảng Bình đã tận tình giảng dạy, truyền đạt những kiến thức quý báu
và tạo điều kiện cho em hoàn thành báo cáo này
Mặc dù đã cố gắng rất nhiều để hoàn thành đề tài với tất cả sự nổ lực của bản thân, nhưng không sao tránh khỏi những thiếu sót Em rất mong nhận được sự ủng hộ
và giúp đỡ của các thầy cô và các bạn
Quảng Bình, ngày 20 tháng 05 năm 2017
Sinh viên thực hiện
Phạm Tuấn Vũ
Trang 2MỞ ĐẦU 1
1 Lý do chọn đề tài 1
2 Mục tiêu nghiên cứu 1
3 Nội dung nghiên cứu 1
4 Đối tượng, phạm vi nghiên cứu 1
5 Phương pháp nghiên cứu 1
CHƯƠNG 1: ĐẠI CƯƠNG VỀ LÝ THUYẾT ĐỒ THỊ 3
1.1 Một số khái niệm liên quan đến đồ thị 3
1.1.1 Định nghĩa đồ thị 3
1.1.2 Các loại đồ thị 3
1.2 Đồ thị con, đồ thị bộ phận và tính liên thông trong đồ thị 3
1.2.1 Đồ thị con, đồ thị bộ phận 3
1.2.2 Tính liên thông trong đồ thị 3
1.3 Đồ thị Euler, đồ thị nửa Euler và đồ thị Hamilton 4
1.3.1 Đồ thị Euler và đồ thị nửa Euler 4
1.3.2 Đồ thị Hamilton 8
1.4 Biểu diễn đồ thị trên máy tính 8
1.4.1 Biểu diễn bằng ma trận kề, ma trận trọng số: 8
1.4.2 Danh sách cạnh 9
1.4.3 Danh sách kề 9
CHƯƠNG 2: GIỚI THIỆU MỘT SỐ THUẬT TOÁN TRÊN ĐỒ THỊ 12
2.1 Thuật toán tìm kiếm trên đồ thị 12
2.1.1 Tìm kiếm theo chiều sâu trên đồ thị 12
2.1.2 Tìm kiếm theo chiều rộng trên đồ thị 12
2.1.3 Tìm đường đi và kiểm tra tính liên thông 14
2.2 Đồ thị có trọng số và bài toán tìm đường đi ngắn nhất 14
2.2.1 Đường đi ngắn nhất trong đồ thị không có trọng số 14
2.2.2 Tìm đường đi ngắn nhất 15
2.2.3 Thuật toán Ford – Bellman 15
2.2.4 Thuật toán Dijkstra 15
2.2.5 Thuật toán Floyd – đường đi ngắn nhất giữa tất cả các cặp đỉnh 16
CHƯƠNG 3: LUỒNG CỰC ĐẠI VÀ HƯỚNG ỨNG DỤNG 18
3.1 Giới thiệu luồng cực đại 18
3.1.1 Bài toán luồng trên mạng 18
3.1.2 Bài toán luồng cực đại trong mạng 18
3.1.3 Mạng, luồng trong mạng, bài toán luồng cực đại 18
3.2 Ứng dụng bài toán luồng cực đại trong mạng 19
Trang 33.3 Một số bài toán tối ưu tổ hợp ứng dụng từ bài toán luồng 25
3.3.1 Bài toán về thủy lợi 26
3.3.2 Bài toán về hệ thống đại diện chung 27
3.3.3 Về một bài toán tối ưu rời rạc 27
3.4 Kết luận 28
CHƯƠNG 4: MÔ PHỎNG THUẬT TOÁN 29
4.1 Phát biểu bài toán 29
4.2 Yêu cầu bài toán 30
4.3 Cấu trúc chương trình 31
4.4 Hoạt động của chương trình 33
4.4.1 Chức năng các file class trong chương trình 34
4.4.2 Trình tự hoạt động 35
KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 36
TÀI LIỆU THAM KHẢO 37
PHỤ LỤC 38
Trang 4Linked Adjancency List Danh sách kề liên kết Strongly connected Liên thông mạnh
Depth first search (DFS) Tìm kiếm sâu
Trang 5DANH MỤC HÌNH ẢNH
Hình 1.1 Đồ thị liên thông, đồ thị không liên thông 4
Hình 1.2 Liên thông mạnh và liên thông yếu 4
Hình 1.3 Bảy cây cầu trên sông Pregel 5
Hình 1.4 Đồ thị biểu diễn thành phố Konigsberg 5
Hình 1.5 Đồ thị Euler và đồ thị nửa Euler 6
Hình 1.6 Đường đi Hamilton 8
Hình 1.7.Đồ thị vô hướng G và Đồ thị có hướng G1 9
Hình 4.1 Cấu trúc chương trình 31
Hình 4.2 Giao diện của ứng dụng 32
Hình 4.3 Giao diên chạy ứng dụng 32
Hình 4 4 Vẽ điểm 33
Hình 4.5 Vẽ đường 34
Hình 4.6 Các chức năng trong chương trình 35
Trang 6MỞ ĐẦU
1 Lý do chọn đề tài
Trong những năm trở lại đây, cùng với sự ra đời của máy tính điện tử và sự phát triển nhanh chóng của Tin học, lý thuyết đồ thị càng được quan tâm đến nhiều hơn Đặc biệt là các thuật toán trên đồ thị đã có nhiều ứng dụng trong nhiều lĩnh vực khác nhau như: Mạng máy tính, Lý thuyết mã, Tối ưu hoá, Kinh tế học v.v Nó trả lời cho câu hỏi: Hai máy tính trong mạng có thể liên hệ được với nhau hay không? Hay vấn đề phân biệt hai hợp chất hoá học có cùng công thức phân tử nhưng lại khác nhau về công thức cấu tạo cũng được giải quyết nhờ mô hình đồ thị
Lý thuyết đồ thị không những có nhiều ứng dụng trong thực tế mà còn là công cụ đắc lực cho ngành công nghệ thông tin Nó giúp cho chúng ta mô tả một cách dễ dàng các bài toán phức tạp cụ thể, để từ đó ta có thể mã hoá các bài toán đó vào máy tính Hiện nay có nhiều tài liệu, sách, giáo trình đã viết về lý thuyết đồ thị với những nội dung, đầy đủ giúp cho những người muốn nghiên cứu về lý thuyết đồ thị tham khảo Tuy nhiên hầu hết các tài liệu đều chỉ nghiên cứu về lý thuyết và xây dựng các thuật toán chung cho các bài toán mà chưa có nhiều tài liệu viết về các ứng dụng các thuật toán để giải bài toán ứng dụng cụ thể Để hiện thực hóa trong việc học tập, giảng dạy Tin học ở các trường Trung học phổ thông cũng như các trường Đại học, Cao
đẵng thì luận văn “Tìm hiểu thuật toán tối ưu trên đồ thị và hướng ứng dụng ” là
thực sự cần thiết
2 Mục tiêu nghiên cứu
Mục tiêu chính của đề tài là nghiên cứu về lý thuyết về đồ thị và một số thuật toán ứng dụng đồ thị vào học tập cũng như cuộc sống
3 Nội dung nghiên cứu
- Chương I: Tổng quan về lý thuyết đồ thị
- Chương II: Một số bài toán tối ưu trên đồ thị
- Chương III: Luồng cực đại và các hướng ứng dụng
- Chương IV: Mô phỏng thuật toán
4 Đối tượng, phạm vi nghiên cứu
- Đối tượng nghiên cứu: Lý thuyết về đồ thị và ứng dụng đồ thị
- Phạm vi nghiên cứu: Lý thuyết đồ thị, ứng dụng, xây dựng, lập trình mô phỏng
và hệ thống hóa ứng dụng các thuật toán liên quan đến đồ thị nhằm phục vụ cho việc học tập cũng như việc giảng dạy trong nhà trường
5 Phương pháp nghiên cứu
- Phương pháp nghiên cứu lý thuyết:
+ Nghiên cứu lý thuyết về đồ thị, các thuật toán ứng dụng của đồ thị
+ Hệ thống hóa một số ứng dụng của đồ thị
Trang 7- Phương pháp nghiên cứu thực nghiệm:
Sử dụng phương pháp nghiên cứu lý thuyết kết hợp với nghiên cứu thực nghiệm: + Nghiên cứu, tìm hiểu ứng dụng liên quan đến đề tài trong thực tế
+ Viết chương trình cho bài toán ứng dụng cụ thể
Trang 8CHƯƠNG 1: ĐẠI CƯƠNG VỀ LÝ THUYẾT ĐỒ THỊ 1.1 Một số khái niệm liên quan đến đồ thị
1.1.1 Định nghĩa đồ thị
Định nghĩa: Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối các
đỉnh của đồ thị Các loại đồ thị khác nhau được phân biệt bởi kiểu và số lượng cạnh nối hai đỉnh nào đó của đồ thị [2]
- Nếu cạnh u = (x,y) mà x và y là hai đỉnh phân biệt thì ta nói x, y là hai đỉnh kề nhau
- Nếu u = (x,x) thì u là cạnh có hai đỉnh trùng nhau ta gọi đó là một khuyên
- Nếu u = (x,y) mà x,y là cặp đỉnh có phân biệt thứ tự hay có hướng từ x đến y thì
u là một cung, khi đó x là gốc còn y là ngọn hoặc x là đỉnh ra, y là đỉnh vào
- Khi giữa cặp đỉnh (x, y) có nhiều hơn một cạnh thì ta nói những cạnh cùng cặp đỉnh là những cạnh song song hay là cạnh bội
phân biệt thứ tự Đồ thị có hướng là đồ thị mà mọi u=(x, y) ε X đều là cung [2]
1.2 Đồ thị con, đồ thị bộ phận và tính liên thông trong đồ thị
1.2.2 Tính liên thông trong đồ thị
1.2.2.1 Tính liên thông trong đồ thị vô hướng
Định nghĩa: Một đồ thị được gọi là liên thông nếu có đường đi giữa mọi cặp
đỉnh phân biệt của đồ thị Ngược lại, đồ thị này được gọi là không liên thông [2] G: liên thông;
H: không liên thông
Trang 9
Hình 1.1 Đồ thị liên thông, đồ thị không liên thông
Cho đồ thị G=(V,E) và v V V' là tập hợp các đỉnh của V liên thông với v, E' là tập hợp các cạnh nối 2 đỉnh của V' Khi đó đồ thị G' = (V',E') gọi là thành phần liên thông (connected component) của G chứa v Đương nhiên nếu v và u liên thông trong
G thì thành phần liên thông của G chứa v cũng là thành phần liên thông chứa u
Định lý: Đồ thị G=(V, E) là liên thông khi và chỉ khi G có duy nhất một thành
phần liên thông [2]
1.2.2.2 Tính liên thông trong đồ thị có hướng
G gọi là liên thông mạnh nếu luôn tồn tại đường đi (theo các cung định hướng) giữa hai đỉnh bất kỳ của đồ thị, g gọi là liên thông yếu nếu đồ thị vô hướng nền của nó
là liên thông
Hình 1.2 Liên thông mạnh và liên thông yếu
Định lý: Nếu trong đồ thị G=(V, E) có đúng hai đỉnh bậc lẻ thì hai đỉnh này phải
liên thông với nhau [2]
Định lý: (Định lý về điều kiện cần và đủ của một đồ thị lưỡng phân)
Đồ thị G = (V, E) là một đồ thị lưỡng phân khi và chỉ khi mọi chu trình của nó đều
có độ dài chẵn [2]
1.3 Đồ thị Euler, đồ thị nửa Euler và đồ thị Hamilton
1.3.1 Đồ thị Euler và đồ thị nửa Euler
Xét bài toán 7 cây cầu ở Konigsberg [3]
Thành phố Konigsberg thuộc nước Cộng hoà Litva có con sông Pregel chảy qua, giữa sông có cù lao Kneiphof tạo nên bốn vùng đất Người ta đã xây dựng 7 cây cầu để nối các vùng đất này lại với nhau
Trang 10Năm 1736 L Euler, nhà toán học người Thuỵ Sĩ đã đưa ra bài toán sau đây: Hỏi
có thể đi qua cả 7 cây cầu, mỗi cầu chỉ đi qua một lần rồi quay trở về đúng chỗ 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 Sau đó, chính L Euler đã chứng minh được rằng bài toán trên là không giải được
Hình 1.3 Bảy cây cầu trên sông Pregel
Nếu biểu diễn mỗi vùng đất: A, B, C, D bằng đỉnh của một đa đồ thịvô hướng và
có cạnh nối giữa chúng nếu có cầu nối tương ứng, thì bài toán trên đưa về việc tìm một chu trình đi qua mỗi cạnh của đồ thị đúng một lần
Hình 1.4 Đồ thị biểu diễn thành phố Konigsberg
Trong lý thuyết đồ thị, cho đồ thị G=(V,E), trong đó V là tập hợp các đỉnh, E là tập hợp các cạnh Từ bài toán trên, người ta đã đưa ra các khái niệm, định nghĩa về chu trình và đường đi Euler
- Đường đi Euler là đường đi, đi qua tất cả các cạnh của đồ thị, mỗi cạnh đúng một
lần trong đó điểm đầu và điểm cuối không trùng nhau
- Chu trình Euler là chu trình đi qua tất cả các cạnh của đồ thị, mỗi cạnh đúng một
lần trong đó đỉnh đầu và đỉnh cuối trùng nhau (đồ thị có thể có các đỉnh cô lập)
Trang 11- Đồ thị gọi là đồ thị Euler khi nó chứa chu trình Euler, và được gọi là nửa Euler
khi nó chứa đường đi Euler
- Đối với các đồ thị có hướng, các thuật ngữ đường đi và chu trình được thay bằng đường đi có hướng và chu trình có hướng
Một đồ thị là Euler thì sẽ là nửa Euler, điều ngược lại là không đúng
Hình 1.5 Đồ thị Euler và đồ thị nửa Euler
Từ các định nghĩa trên, ta có điều kiện cần và đủ cho sự tồn tại của chu trình vô hướng Euler như sau:
Định lý 1 (Định lý Euler): Đồ thị G có chu trình Euler khi và chỉ khi G liên thông
và mọi đỉnh có bậc chẵn khác 0 [2]
(): Giả sử G có chu trình Euler và v là đỉnh bất kỳ của G Khi đó chu trình Euler đến v theo cạnh e thì ra khỏi v bằng cạnh e’ e Do đó bậc của v phải là số chẵn
G hiển nhiên là liên thông
(): Giả sử G liên thông và mọi đỉnh có bậc chẵn khác 0 Ta chứng minh G có chu trình Euler quy nạp theo số cạnh m của G
m = 1: Vì G liên thông và mọi đỉnh bậc chẵn nên G chỉ có 1 đỉnh và 1 khuyên Khuyên đó cũng tạo thành chu trình Euler
Giả sử G có m cạnh, số đỉnh n > 0 và mọi đồ thị liên thông có số cạnh nhỏ hơn m với mọi đỉnh bậc chẵn đều có chu trình euler
+ Trường hợp n = 1 hoặc 2 thì hiển nhiên tồn tại chu trình Euler
+ Trường hợp n > 2 Vì bậc của các đỉnh chẵn 2, bao giờ cũng chọn được 3 đỉnh
a, b, c với các cạnh x = (a,b), y = (a,c)
G’ có 2 thành phần liên thông G1 và G2 Không mất tính tổng quát giả sử G1 chứa
a, G2 chứa b và c G1 có chu trình Euler C1, G2 có chu trình Euler C2 Ta xây dựng chu trình Euler C của G như sau Xuất phát từ đỉnh a đi theo chu trình C1 quay về a,
Trang 12sau đó đi theo cạnh x = (a, b) đến đỉnh b, từ b đi theo chu trình C2 quay về b, sau đó đi theo cạnh z = (b, c) và y = (c, a) quay về a
G’ có 3 thành phần liên thông G1, G2 và G3 Không mất tính tổng quát giả sử G1 chứa a, G2 chứa b và G3 chứa c G1 có chu trình Euler C1, G2 có chu trình Euler C2, G3 có chu trình Euler C3 Ta xây dựng chu trình Euler C của G như sau Xuất phát từ đỉnh a đi theo chu trình C1 quay về a, sau đó đi theo cạnh x= (a, b) đến đỉnh b, từ b đi theo chu trình C2 quay về b, sau đó đi theo cạnh z= (b, c) đến đỉnh c, từ c đi theo chu trình C3 quay về c, sau đó đi theo cạnh y= (c, a) quay về a
Giả sử G không chứa cạnh z = (b, c)
Xét đồ thị G’ thu được từ G bằng cách loại bỏ 2 cạnh x, y và thêm cạnh z Sẽ xảy
ra 1 trong hai khả năng sau:
G’ liên thông Vì số cạnh của G’ nhỏ hơn m và các đỉnh vẫn có bậc chẵn nên theo giả thiết quy nạp tồn tại chu trình Euler C’ của G’ Thay cạnh z C’ bằng cạnh x và y
ta thu được chu trình Euler C của G
G’ có 2 thành phần liên thông G1 và G2 Không mất tính tổng quát giả sử G1 chứa
a, G2 chứa b và c G1 có chu trình Euler C1, G2 có chu trình Euler C2 Ta xây dựng chu trình Euler C của G như sau Thay cạnh zC2 bằng các cạnh x và y ta có chu trình C2’ Nối C2’ với C1 ta thu được chu trình Euler C của G
Định lý 2: Cho đồ thị G có k đỉnh bậc lẻ Khi đó số đường đi tối thiểu phủ G là
k/2
Ta đã biết số đỉnh bậc lẻ là chẵn, k=2n Chứng minh quy nạp theo n [3]
n=1: Nối 2 đỉnh bậc lẻ với nhau bằng cạnh z ta thu được đồ thị G’ thoả định lý Euler Như vậy G’ có chu trình Euler C’ Bỏ cạnh z trên C’ ta thu được đường đi Euler phủ G
Giả sử G có số đỉnh bậc lẻ là 2n và định lý đúng với k<2n Nối 2 đỉnh bậc lẻ a, b nào đó với nhau bằng cạnh z ta thu được đồ thị G’ có 2n-2 đỉnh bậc lẻ Theo giả thiết quy nạp G’ có n-1 đường đi phủ G’ Gọi P là đường đi qua cạnh z Hiển nhiên a, b không phải đỉnh đầu hoặc cuối của P, vì vậy nếu bỏ cạnh z ta thu được 2 đường đi P1
và P2 cùng với n-2 đường đi còn lại phủ đồ thị G
Bây giờ xét đồ thị có hướng G = (V, A) Ký hiệu:
I
O v d v
Trang 13Đồ thị G3 không có chu trình Euler nhưng nó có đường đi Euler a - c - d - e - b - c-
a - b, vì thế G3 là đồ thị nửa Euler
Đồ thị G2 không có chu trình Euler cũng như đường đi Euler
1.3.2 Đồ thị Hamilton
1.3.2.1 Chu trình Hamilton
Định nghĩa: Giả sử G = <X, U> là đồ thị vô hướng
Chu trình Hamilton là chu trình đi qua tất cả các đỉnh của đồ thị, mỗi đỉnh đúng một lần
1.3.2.2 Đường Hamilton
Định nghĩa: Đường Hamilton trong đồ thị G = <X, U> là đường đi qua tất cả các
đỉnh mỗi đỉnh đúng một lần
Hình 1.6 Đường đi Hamilton
1.4 Biểu diễn đồ thị trên máy tính
Để lưu trữ đồ thị và thực hiện các thuật toán khác nhau với đồ thị trên máy tính cần phải tìm những cấu trúc dữ liệu thích hợp để mô tả đồ thị Việc chọn cấu trúc dữ liệu nào để biểu diễn đồ thị có tác động rất lớn đến hiệu quả của thuật toán
Vì vậy, việc chọn lựa cấu trúc dữ liệu để biểu diễn đồ thị phụ thuộc vào từng tình huống cụ thể (bài toán và thuật toán cụ thể) Trong mục này chúng ta sẽ xét một số phương pháp cơ bản được sử dụng để biểu diễn đồ thị trên máy tính, đồng thời cũng
phân tích một cách ngắn gọn những ưu điểm cũng như những nhược điểm của chúng
1.4.1 Biểu diễn bằng ma trận kề, ma trận trọng số:
1.4.1.1 Ma trận kề
Xét đơn đồ thị vô hướng G=(V,E), với tập đỉnh V={ 1, 2, ,n} , tập cạnh E={ e1,
e2, .,em } Ta gọi ma trận kề của đồ thị G là ma trận
A={ ai,j : i,j=1, 2, ,n}
Với các phần tử được xác định theo qui tắc sau đây:
ai, j = 0, nếu (i,j) ∈ E và
ai,j = 1 , nếu (i,j) ∈ E, i, j=1, 2, .,n
Ví dụ: Ma trận trận kề của đồ thị vô hướng cho trong hình 1 là:
Trang 14Hình 1.7.Đồ thị vô hướng G và Đồ thị có hướng G 1 1.4.1.2 Ma trận trọng số
Trong rất nhiều vấn đề ứng dụng của lý thuyết đồ thị, mỗi cạnh e=(u,v) của đồ thị được gán với một con số c(e) (còn viết là c(u,v) gọi là trọng số của cạnh e Đồ thị trong trường hợp như vậy được gọi là đồ thị có trọng số Trong trường hợp đồ thị có
trọng số, thay vì mà trận kề, để biểu diễn đồ thị ta sử dụng ma trận trọng số
C= {c[i,j], i,j=1, 2, .,n}
với
c[i,j]=c(i,j) nếu (i,j) ∈ E
và c[i,j]= θ nếu (i,j) ∈ E
Ưu điểm lớn nhất của phương pháp biểu diễn đồ thị bằng ma trận kề (hoặc ma trận trọng số) là để trả lời câu hỏi: Hai đỉnh u,v có kề nhau trên đồ thị hay không, chúng ta chỉ phải thực hiện một phép so sánh nhược điểm lớn nhất của phương pháp này là: không phụ thuộc vào số cạnh của đồ thị, ta luôn phải sử dụng n2
đơn vị bộ nhớ để lưu trữ ma trận kề của nó
sử dụng 2m đơn vị bộ nhớù Nhược điểm của cách biểu diễn này là để xác định những đỉnh nào của đồ thị là kề với một đỉnh cho trước chúng ta phải làm cỡ m phép so sánh (khi duyệt qua danh sách tất cả các cạnh của đồ thị)
Chú ý: Trong trường hợp đồ thị có trọng số ta cần thêm m đơn vị bộ nhớ để lưu trữ
trọng số của các cạnh
1.4.3 Danh sách kề
Trong rất nhiều vấn đề ứng dụng của lý thuyết đồ thị, cách biểu diễn đồ thị dưới dạng danh sách kề là cách biểu diễn thích hợp nhất được sử dụng
Trang 15Trong cách biểu diễn này, với mỗi đỉnh v của đồ thị chúng ta lưu trữ danh sách các đỉnh kề với nó, mà ta sẽ ký hiệu là: Ke(v)= u∈ V: (v,u)∈ E
Khi đó vòng lặp thực hiện với mỗi một phần tử trong danh sách này theo thứ tự các phần tử được sắp xếp trong nó sẽ được viết như sau: for u∈ Ke(v) do
Chẳng hạn, trên PASCAL có thể mô tả danh sách này như sau (Gọi là cấu
Có thể thay thế bởi cấu trúc lệnh cụ thể trên PASCAL như sau:
For i:=Tro[v] to Tro[v+1]-1 do
từ bàn phím và đưa danh sách đó ra màn hình sau đây:
next:link;
End;
Var
Trang 16j,x,y,m,n,u,v:integer;
t:link;
Ke:array[1 .Vmax] of link;
Begin Write(‘Cho so canh va dinh cua do thi:’); readln(m,n);
(*Khoi tao*)
for j:=1 to n do Ke[j]:=nil;
for j:=1 to m do begin
write(‘Cho dinh dau va cuoi cua canh ‘,j,’:’);
readln(x,y);
new(t); t^.v:=x, t^.next:=Ke[y]; Ke[y]:=t;
new(t); t^.v:=y, t^.next:=Ke[x]; Ke[x]:=t;
end;
writeln(‘Danh sach ke cua cac dinh cua do thi:’);
for J:=1 to m do begin
writeln(‘Danh sachcac dinh ke cua dinh ‘,j,’:’);
t:=Ke[j];
while t^.next<>nil do begin
Kết luận: Lý thuyết đồ thị là mảng rất lớn nằm trong toán rời rạc, đồ thị đóng vai
trò quan trọng làm cơ sở toán cho tin học và có nhiều ứng dụng trong thực tiễn Vì vậy việc nghiên cứu cơ sở lý thuyết đồ thị là rất cần thiết giúp cho việc ứng dụng xây dựng các thuật toán của đồ thị Trong phạm vi nghiên cứu đề tài, những vấn đề mà tôi nêu trên là một phần của lý thuyết đồ thị, nhằm mục đích phục vụ cho quá trình nghiên cứu các chương sau
Trang 17CHƯƠNG 2: GIỚI THIỆU MỘT SỐ THUẬT TOÁN TRÊN ĐỒ THỊ 2.1 Thuật toán tìm kiếm trên đồ thị
2.1.1 Tìm kiếm theo chiều sâu trên đồ thị
Tìm kiếm ưu tiên chiều sâu hay tìm kiếm theo chiều sâu (DFS) là một thuật toán duyệt hoặc tìm kiếm trên một cây hoặc một đồ thị Thuật toán khởi đầu tại gốc (hoặc chọn một đỉnh nào đó coi như gốc) và phát triển xa nhất có thể theo mỗi nhánh
Ý tưởng thuật toán:
1 DFS trên đồ thị vô hướng cũng giống như khám phá mê cung với một cuộn
chỉ và một thùng sơn đỏ để đánh dấu, tránh bị lạc Trong đó mỗi đỉnh s trong đồ thị
tượng trưng cho một cửa trong mê cung
2 Ta bắt đầu từđỉnhs, buộc đầu cuộn chỉ vàosvà đánh đấuđỉnhnày"đã thăm" Sau đó ta đánh dấuslàđỉnhhiện hànhu
3 Bây giờ, nếu ta đi theocạnh(u,v)bất kỳ
4 Nếucạnh(u,v)dẫn chúng ta đếnđỉnh"đã thăm"v, ta quay trở vều
5 Nếuđỉnhvlàđỉnhmới, ta di chuyển đếnvvà lăn cuộn chỉ theo Đánh dấuvlà"đã thăm" Đặtvthànhđỉnhhiện hành và lặp lại các bước
6 Cuối cùng, ta có thể đi đến mộtđỉnhmà tại đó tất cả các cạnh kề với nó đều dẫn chúng ta đến cácđỉnh"đã thăm" Khi đó, ta sẽ quay lui bằng cách cuộn ngược cuộn chỉ và quay lại cho đến khi trở lại mộtđỉnh kềvới mộtcạnhcòn chưa được khám phá Lại tiếp tục quy trình khám phá như trên
7 Khi chúng ta trở vềsvà không còncạnhnào kề với nó chưa bị khám phá là lúcDFSdừng
if Chuaxet[u] then DFS(u);
end; (* đỉnh v là đã duyệt xong *)
Khi đó, tìm kiếm theo chiều sâu trên đồ thị được thực hiện nhờ thuật toán sau:
Trang 18Trong lý thuyết đồ thị, tìm kiếm theo chiều rộng (BFS) là một thuật toán tìm kiếm trong đồ thị trong đó việc tìm kiếm chỉ bao gồm 2 thao tác: (a) cho trước một đỉnh của đồ thị; (b) thêm các đỉnh kề với đỉnh vừa cho vào danh sách có thể hướng tới tiếp theo
Ý tưởng:
Thuật toán sử dụng một cấu trúc dữ liệu hàng đợi để lưu trữ thông tin trung gian
thu được trong quá trình tìm kiếm:
1 Chèn đỉnh gốc vào hàng đợi (đang hướng tới)
2 Lấy ra đỉnh đầu tiên trong hàng đợi và quan sát nó
Nếu đỉnh này chính là đỉnh đích, dừng quá trình tìm kiếm và trả về kết quả
Nếu không phải thì chèn tất cả các đỉnh kề với đỉnh vừa thăm nhưng chưa được quan sát trước đó vào hàng đợi
3 Nếu hàng đợi là rỗng, thì tất cả các đỉnh có thể đến được đều đã được quan sát
– dừng việc tìm kiếm và trả về "không thấy"
4 Nếu hàng đợi không rỗng thì quay về bước 2
Thuật toán:
Procedure BFS(v);
(* Tìm kiếm theo chiều rộng bắt đầu từ đỉnh v; Các biến
Chuaxet, Ke là biến toàn cục *)
Trang 19END
2.1.3 Tìm đường đi và kiểm tra tính liên thông
Bài toán tìm đường đi giữa hai đỉnh
Giả sử s và t là hai đỉnh nào đó của đồ thị, tìm đường đi từ s đến t Như trên đã phân tích, thủ tục DFS(s) (BFS(s)) sẽ cho phép thăm tất cả các đỉnh thuộc cùng một thành phần liên thông với s Sau khi thực hiện xong thủ tục, nếu Chuaxet[t] = true, điều đó có nghĩa là không có đường đi từ s đến t, còn nếu Chuaxet[t]=false thì t thuộc cùng thành phần liên thông với s, hay nói một cách khác tồn tạiđường đi từ s đến t Trong trường hợp tồn tại đường đi, ta dùng biến Truoc[v] để ghi nhận đỉnh trước đỉnh
v trong đường đi tìm kiếm từ s đến v Khi đó, đối với thủ tục DFS(v) cần sửa câu lệnh
2.2 Đồ thị có trọng số và bài toán tìm đường đi ngắn nhất
2.2.1 Đường đi ngắn nhất trong đồ thị không có trọng số
Đồ thị không có trọng số là đồ thị hữu hạn trên các cạnh không có trọng số Bài toán tìm đường đi ngắn nhất giữa hai đỉnh a,b trong đồ thị không có trọng số G= <X, U> là tìm đường đi giữa hai đỉnh a, b sao cho có số các cạnh là ít nhất [4]
Thuật toán
Bước 1: Tại đỉnh a ta ghi số 0; Các đỉnh có cạnh đi từ đỉnh a đến ta ghi số 1
Giả sử ta đã ghi tới i, tức là ta đã đánh số được các tập đỉnh là A(0) = {a}, A(1), A(2), , A(i) trong đó A(i) là tập tất cả các đỉnh được ghi bởi số i Ta xác định tập đỉnh được đánh số bởi số i + 1 là A(i+1) = {x / x X, x A(k) với k = 0, ,i và tồn tại y A(i) sao cho từ y có cạnh (cung) tới x} Do tính hữu hạn của đồ thị, sau một số hữu hạn các bước, thuật toán dừng lại và cho kết quả là tập các đỉnh có chứa b được đánh
số bởi m là A(m)
Bước 2: Do bước 1 thì đỉnh b được đánh số bởi m, điều này chứng tỏ đường đi từ
a đến b có m cạnh (cung) và là đường ngắn nhất đi từ a đến b Để tìm tất cả các đường
có độ dài m ngắn nhất đi từ a đến b, ta xuất phát từ b đi ngược về a theo đúng nguyên tắc:
Trang 20- Tìm tất cả các đỉnh có cạnh tới b được ghi số m-1, giả sử đó là x[i,k] (k=1,2, )
- Với mỗi đỉnh x[i,k] tìm tất cả các đỉnh có cạnh với x[i,k] (k=1,2 ) ghi số m-2 Bằng cách lùi dần trở lại, đến một lúc nào đó gặp đỉnh ghi số 0, đó chính là đỉnh a Tất cả các đường xác định theo các bước trên là đường đi từ a đến b có độ dài ngắn nhất là m cần tìm
2.2.2 Tìm đường đi ngắn nhất
Trong phần này chúng ta chỉ xét đồ thị có hướng G=(V,E), |V| = n, |E|=m với các cung được gán trọng số, nghĩa là, mỗi cung (u,v) E của nó được đặt tương ứng với một
số thực a(u,v) gọi là trọng số của nó
2.2.3 Thuật toán Ford – Bellman
Procedure Ford_Bellman;
Đầu vào: Đồ thị có hướng G=(V,E) với n đỉnh, s ∈ V là đỉnh xuất phát, a[u,v], u,
v ∈ V, ma trận trọng số;
Giả thiết: Đồ thị không có chu trình âm
Đầu ra: Khoảng cách từ đỉnh s đến tất cả các đỉnh còn lại d[v],
Truoc[v], ghi nhận đỉnh đi trước v trong đường đi ngắn nhất từ s đến v
Begin (* Khởi tạo *)
for v V do begin d[v]:= a[s,v];
if d[v] > d[u] + a[u,v] then begin
d[v]:= d[u] + a[u,v];
Truoc[v]:= u;
end;
end;
2.2.4 Thuật toán Dijkstra
Bài toán: Cho một đồ thị có hướng G=(V,E), một hàm trọng số w: E → [0, ∞) và
một đỉnh nguồn s Cần tính toán được đường đi ngắn nhất từ đỉnh nguồn s đến mỗi đỉnh của đồ thị
Ví dụ: Chúng ta dùng các đỉnh của đồ thị để mô hình các thành phố và các cạnh
để mô hình các đường nối giữa chúng Khi đó trọng số các cạnh có thể xem như độ dài của các con đường (và do đó là không âm) Chúng ta cần vận chuyển từ thành phố A
Trang 21đến thành phố B Thuật toán Dijkstra sẽ giúp chỉ ra đường đi ngắn nhất chúng ta có thể
đi
Trọng số không âm của các cạnh của đồ thị mang tính tổng quát hơn khoảng cách hình học giữa hai đỉnh đầu mút của chúng Ví dụ, với 3 đỉnh X, Y, Z đường đi X-Y-Z
có thể ngắn hơn so với đường đi trực tiếp X-Y
Ý tưởng: Ý tưởng của thuật toán được chứng minh như sau
Chúng ta sẽ chỉ ra, khi một đỉnh v được bổ sung vào tập S, thì d[v] là giá trị
của đường đi ngắn nhất từ nguồn s đến v
Theo định nghĩa nhãn d, d[v] là giá trị của đường đi ngắn nhất trong các đường đi
từ nguồn s, qua các đỉnh trong S, rồi theo một cạnh nối trực tiếp u-v đến v
Giả sử tồn tại một đường đi từ s đến v có giá trị bé hơn d[v] Như vậy trong đường
đi, tồn tại đỉnh giữa s và v không thuộc S Chọn w là đỉnh đầu tiên như vậy
Thuật toán:
procedure Dijkstra;
(* Đầu vào:đồ thị có hướng G=(V,E) với n đỉnh
s ∈ V là đỉnh xuất phát, a[u,v],u.v ∈ V, ma trận trọng số;
Giả thiết : a[u,v] 0, u,v V
Đầu ra: Khoảng cách từ đỉnh s đến tất cả các đỉnh còn lại d[v,
v ∈V Truoc[v],v ∈ V ghi nhận đỉnh đi trước v trong đường đi ngắn nhất từ s đến v*)
Begin (*khởi tạo*)
for v T do (* Gán lại nhãn cho các đỉnh trong T *)
if d[v] > d[u] + a[u,v] then
begin d[v]:= d[u] + a[u,v];
Trang 22Cho G=(V,E) là một đồ thị có hướng, có trọng số Để tìm đường đi ngắn nhất giữa
mọi cặp đỉnh của G, ta áp dụng thuật toán Dijkstra nhiều lần hoặc áp dụng thuật toán Floyd được trình bày dưới đây
Giả sử V={v1, v2, , vn} và có ma trận trọng số là W W0 Thuật toán Floyd xây dựng dãy các ma trận vuông cấp n là Wk ( 0 ≤ 𝑘 ≤ 𝑛 )
Procedure Floyd
Procedure Floyd;
(* Tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh
Đầu vào: Đồ thị cho bởi ma trận trọng số a[i,j], i, j =1, 2, ,n
Đầu ra:
Ma trận đường đi ngắn nhất giữa các cặp đỉnh
d[i,j]=, i,j = 1, 2 .,n,
trong đó d[i,j] cho độ dài đường đi ngắn nhất từ đỉnh i đến đỉnh j
Ma trận ghi nhận đường đi
Trang 23CHƯƠNG 3: LUỒNG CỰC ĐẠI VÀ HƯỚNG ỨNG DỤNG 3.1 Giới thiệu luồng cực đại
3.1.1 Bài toán luồng trên mạng
Nhiều bài toán quy hoạch tuyến tính có thể quy về bài toán làm cực tiểu phí tổn vận chuyển hàng trong một mạng (gồm các nút và các cung đường) sao cho đảm bảo được các nhu cầu ở một số nút khi đã biết nguồn cung cấp tại một số nút khác
Các bài toán như vậy được gọi là các bài toán luồng trên mạng hoặc bài toán tuyến tính Lớp này bao gồm các bài toán quen thuộc trong thực tế như: bài toán vận tải, các bài toán mạng điện và mạng giao thông, các bài toán quản lý và phân bổ vật tư, bài toán bổ nhiệm, bài toán kế hoạch tài chính, bài toán đường ngắn nhất, bài toán luồng cực đại …[6]
3.1.2 Bài toán luồng cực đại trong mạng
Bài toán luồng cực đại [1] trong mạng cũng là một trong số những bài toán tối ưu trên đồ thị tìm được những ứng dụng rộng rãi trong thực tế cũng như những ứng dụng thú vị trong lý thuyết tổ hợp Bài toán được đề xuất vào đầu những năm 1950, và gắn liền với tên tuổi của hai nhà bác học Mỹ là L.R.Fordvà D.R.Fulkerson Bài toán luồng cực đại trong mạng có nhiều ứng dụng trong thực tế như: Bài toán xác định cường độ dòng lớn nhất của dòng vận tải giữa hai nút của một bản đồ giao thông, bài toán tìm luồng dầu lớn nhất có thể bơm từ tàu chở dầu vào bể chứa của một hệ thống đường ống dẫn dầu…Ngoài ra, ứng dụng của bài toán còn để giải các bài toán như: Bài toán đám cưới vùng quê, bài toán về hệ thống đại diện chung, bài toán phân nhóm sinh hoạt, bài toán lập lịch cho hội nghị…
3.1.3 Mạng, luồng trong mạng, bài toán luồng cực đại
Định nghĩa 1: Mạng (Network) [1]
Ta gọi mạng là đồ thị có hướng G=(V,E), trong đó có duy nhất một đỉnh s không
có cung đi vào gọi là điểm phát, duy nhất một đỉnh t không có cung đi ra gọi là điểm thu và mỗi cung e = (v,w) ∈ E được gán với một số không âm c(e) = c(v,w) gọi là khả năng thông qua của cung e
Để thuận tiện cho việc trình bày ta sẽ quy ước rằng nếu không có cung (v,w) thì khả năng thông qua c(v,w) được gán bằng 0
Định nghĩa 2 Luồng (Luồng trong mạng)
Giả sử cho mạng G=(V,E) Ta gọi luồng f trong mạng G=(V,E) là ánh xạ f: E →
R+ gán cho mỗi cung e =(v,w) ∈ E một số thực không âm f(e) = f(v,w), gọi là luông trên cung e, thoả mãn các điều kiện sau:
1 Luồng trên mỗi cung e ∈ E không vượt quá khả năng thông qua của nó: 0 ≤ f (e) ≤ c(e),
2 Điều kiện cân bằng luồng trên mỗi đỉnh của mạng : Tổng luồng trên các cung
đi vào đỉnh v bằng tổng luồng trên các cung đi ra khỏi đỉnh v, nếu v ¹ s,t:
Trang 24()
(
) ( )
(v wV w v E v wV v w E
3.Giá trị của luồng f là số
.),()
,()
(
) ( )
w
t w f w
s f f
val
Tính chất của luồng
Với tập B ⊆ V, ký hiệu:
W-(B) = { (a, b)∈ E | a∉B,b∈B } - tập cạnh từngoài B đi vào B
W+(B) = { (a, b)∈ E | a∈B,b∉B } - tập cạnh từ B đi ra khỏi B
Khi đó nếu tập con các đỉnh B không chứa x0 và z thì: t (W-(B)) =t (W+(B)).Theo tính chất b) của luồng: ∑ t (W-(x)) =∑ t (W+(x))
Cạnh kề với đỉnh x nếu có đỉnh đầu và đỉnh cuối đều nằm trong tập B thì nó sẽ có mặt ở cả hai vế củađẳng thức đúng một lần, do đó có thể giản ước
3.2 Ứng dụng bài toán luồng cực đại trong mạng
Cho mạng G=(V,E) Hãy tìm luồng f* trong mạng với giá trị luồng val(f*) là lớn nhất Luồng như vậy ta sẽ gọi là luồng cực đại trong mạng
Bài toán như vậy có thể xuất hiện trong rất nhiều ứng dụng thực tế Chẳng hạn khi cần xác định cường độ lớn nhất của dòng vận tải giữa 2 nút của một bản đồ giao thông Trong ví dụ này của bài toán luồng cực đại xẽ chỉ cho ta các đoạn đường đông xe nhất
và chúng tạo thành “chỗ hẹp” tương ứng với dòng giao thỗng xét theo hai nút được chọn Một ví dụ khác là nếu xét đồ thị tương ứng với một hệ thống dẫn dầu Trong đó các ống tương ứng với các cung, điểm phát có thể có thể là tàu chở dầu, điểm thu là bể chứa, còn những điểm nối giữa các ống là các nút của đồ thị Khả năng thông qua của các cung tường ứng với tiết diện các ống.Cần phải tìn luộng dầu lớn nhất có thể bơm
từ dầu vào bể chứa
Thuật toán Ford-Fulkerson [4]
Việc chứng minh định lý luồng cực đại-lát cắt cực tiểu ngay lập tức cho chúng ta một thuật toán Tìm luồng cực đại- thuật toán Ford-Fulkerson:
- Khởi tạo một luồng bằng 0
- Trong khi đồ thị tăng luồng của f còn có đường đi cơ bản (đường tăng luồng), thì tìm một đường đi như thế, nâng luồng dọc theo đường đi này
- Khi không còn đường đi cơ bản nữa thì f là luồng cực đại
Đoạn chương trình sau minh họa thuật toán Ford-Fulekerson bằng NNLT Pascal, trong đó sử dụng tìm kiếm sâu DFS để tìm một đường tăng luồng trên đồ thị tăng luồng