NỘI DUNG Nếu như Dijkstra giải quyết bài toán tìm đường đi ngắn nhất từ một đỉnh cho trước đến mọi đỉnh khác trong đồ thị, thì Floyd-Warshall sẽ tìm đường đi ngắn nhất giữa mọi đỉnh sa
Trang 1TRƯỜNG ĐẠI HỌC GIAO THÔNG VẬN TẢI TP HỒ CHÍ MINH
VIỆN ĐÀO TẠO CHẤT LƯỢNG CAO KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO BÀI TẬP LỚN
PHÂN TÍCH THIẾT KẾ GIẢI THUẬT
Nhóm 9
Giáo viên hướng dẫn: Trần Anh Tuấn
Sinh viên MSSV
Nguyễn Việt Long 19H1120052
Trần Đông Dun 19H1120045
Nguyễn Trọng Nhân 19H1120019
Thành phố Hồ Chí Minh
Trang 2NỘI DUNG
Nếu như Dijkstra giải quyết bài toán tìm đường đi ngắn nhất từ một đỉnh cho
trước đến mọi đỉnh khác trong đồ thị, thì Floyd-Warshall sẽ tìm đường đi
ngắn nhất giữa mọi đỉnh sau một lần chạy thuật toán Một tính chất nữa là Floyd-Warshall có thể chạy trên đồ thị có các cạnh có trọng số có thể âm,
tức là không bị giới hạn như Dijkstra Tuy nhiên, lưu ý là trong đồ thị không được có vòng (cycle) nào có tổng các cạnh là âm, nếu có vòng như vậy ta không thể tìm được đường đi ngắn nhất (mỗi lần đi qua vòng này độ dài quãng đường lại giảm, nên ta có thể đi vô hạn lần)
Thuật toán Floyd-Warshall so sánh tất cả các đường đi có thể giữa từng cặp đỉnh Nó là một dạng của quy hoạch động (Dynamic Programming)
Trang 3II CƠ SỞ LÝ THUYẾT
Lý thuyết đồ thị là một ngành khoa học được phát triển từ lâu nhưng lại có nhiều ứng dụng hiện đại Những ý tưởng cơ bản của nó được đưa ra từ thế
kỷ 18 bởi nhà toán học Thụy Sĩ tên là Leonhard Euler Ông đã dùng đồ thị
để giải quyết bài toán 7 chiếc cầu Konigsberg nổi tiếng
Đồ thị cũng được dùng để giải các bài toán trong nhiều lĩnh vực khác nhau Thí dụ, dùng đồ thị để xác định xem có thực hiện một mạch điện trên một bảng điện phẳng được không Chúng ta cũng có thể phân biệt hai hợp chất hóa học có cùng công thức phân tử nhưng có cấu trúc khác nhau nhờ đồ thị Chúng ta cũng có thể xác định xem hai máy tính có được nối với nhau bằng một đường truyền thông hay không nếu dùng mô hình đồ thị mạng máy tính
Đồ thị với các trọng số được gán cho các cạnh của nó có thể dùng để giải các bài toán như bài toán tìm đường đi ngắn nhất giữa hai thành phố trong một mạng giao thông Chúng ta cũng có thể dùng đồ thị để lập lịch thi và phân chia kênh cho các đài truyền hình
Bài toán tìm đường đi ngắn nhất là vấn đề quan trọng trong lý thuyết đồ thị,
nó đã được nghiên cứu từ lâu và có nhiều ứng dụng trong nhiều ngành khoa học nói chung và khoa học máy tính nói riêng Trong thực tế, bài toán này đã được ứng dụng để giải quyết rất nhiều bài toán như điều khiển tối ưu, giao thông vận tải, mạng viễn thông
Nghiên cứu một cách tổng quát, bài toán này có thể chia làm 2 loại:
+ Tìm đường đi ngắn nhất giữa một cặp đỉnh: Cho đồ thị G(V,E,w) có trọng
số cạnh và hai đỉnh u, v thuộc V tìm đường đi ngắn nhất từ đỉnh u đến đỉnh v trên đồ thị G Các giải thuật được phát triển để giải bài toán dạng này tiêu biểu là các giải thuật: Dijkstra, Bellman-Ford,
Trang 4- Tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh: Cho đồ thị G(V,E,w) có trọng số cạnh, tìm đường đi từ đỉnh u đến đỉnh v, với mọi cặp đỉnh u, v thuộc
V Các giải thuật đã được phát triển để giải bài toán này là: Floyd-Warshall, Johnson,
III NỘI DUNG NGHIÊN CỨU
Khi nghiên cứu giải quyết bài toán tìm đường đi ngắn nhất giữa một cặp đỉnh
của đồ thị, một vấn đề được đặt ra là: Với đồ thị có trọng số G(V,E,w) như trên, hãy tìm đường đi ngắn nhất giữa tất cả các cặp đỉnh của đồ thị
Rõ ràng là ta có thể áp dụng thuật toán tìm đường đi ngắn nhất xuất phát từ một đỉnh với n khả năng chọn đỉnh xuất phát Tuy nhiên, với bài toán này, ta
có một cách giải quyết gọn hơn nhiều, đó là sử dụng thuật toán Floyd-Warshall Sau đây chúng ta sẽ tìm hiểu về thuật toán Floyd-Warshall.
1 Mô tả thuật toán:
Đầu vào:
Đồ thị có hướng liên thông G = (V, E), V = {1, 2, , n}, có trọng số với mọi cung (i, j)
Đầu ra:
Ma trận D = [d(i, j)], trong đó d(i, j) là chiều dài đường đi ngắn nhất từ i đến
j với mọi cặp (i, j)
Ma trận P = [p(i,j)] xác định đường đi ngắn nhất giữa mọi cặp đỉnh
Phương pháp:
+ B1 Bước khởi tạo:
Ký hiệu Do là ma trận xuất phát
Do = [do (i, j)]
Trong đó: do(i, j) = w(i, j) nếu tồn tại cung (i, j) và do(i, j) = + nếu không
Trang 5tồn tại cung (i, j) (đặc biệt nếu không có khuyên tại i thì do(i,i)=+).
Ký hiệu Po là ma trận xuất phát
Po = [po (i, j)]
Trong đó: po(i, j) = j nếu có cung từ i đến j và po(i, j) không xác định nếu không có cung từ i đến j
Gán k:= 0
+ B2 Kiểm tra kết thúc:
Nếu k = n, kết thúc D = Dn là ma trận độ dài đường đi ngắn nhất, P=Pn là
ma trận xác định đường đi ngắn nhất
Ngược lại tăng k lên 1 đơn vị (k: = k + 1) và sang B3
+ B3 Tính ma trận Dk theo Dk-1 và Pk theo Pk-1:
Với mọi cặp (i, j), i = 1 n, j = 1 n thực hiện:
Nếu dk-1(i, j) > dk-1(i,k) + dk-1(k,j) thì đặt
dk(i, j) = dk-1(i, k) + dk-1(k, j) và pk(i,j) = pk-1(i,k)
ngược lại đặt
dk(i, j) = dk-1(i, j) và pk(i,j) = pk-1(i,j)
Quay lại B2
Phương pháp xác định đường đi ngắn nhất từ đỉnh i đến đỉnh j:
Đường đi ngắn nhất từ i đến j gồm dãy các đỉnh
i, i1, i2, i3, , ik, ik+1, , im, j
thỏa mãn
i1 = p(i,j), i2 = p(i1,j), , ik+1 = p(ik,j), , p(im,j) = j
2 Thiết kế cấu trúc dữ liệu và giải thuật Floy-Washall:
2.1 Thiết kế cấu trúc:
File dữ liệu đầu vào: FLOYDWAR.INP có cấu trúc
Trang 6 File kết quả: FLOYDWAR.INP
D (Ma trận độ dài đường đi ngắn nhất giữa mọi cặp đỉnh)
P (Ma trận xác định đường đi ngắn nhất giữa mọi cặp đỉnh)
*Ví dụ:
2.2 Giải thuật Floy-Washall:
Giải thuật Floy-Washall xây dựng dãy các ma trận vuông cấp n
D k (0<=k<=n) và ma trận P k (0<=k<=n) như sau:
Trang 73 Phân tích độ phức tạp của thuật toán Floy-Washall:
- Thuật toán Floy-Washall so sánh tất cả các đường đi có thể thông qua đồ thị giữa mỗi cặp đỉnh Nó có thể làm điều này với O(|V|3) so sánh trong biểu
đồ, mặc dù có thể có Ώ (|V| 2 ) các cạnh trong biểu đồ và mọi tổ hợp các cạnh đều được kiểm tra Nó làm như vậy bằng cách cải thiện từng bước một ước lượng trên đường đi ngắn nhất giữa hai đỉnh, cho đến khi ước lượng là tối ưu
- Xem xét một đồ thị G với các đỉnh V đánh số từ 1 đến N Xem xét thêm một chức năng shorestPath(i,j,k) trả về con đường ngắn nhất có thể
từ đến chỉ sử dụng các đỉnh từ tập hợp {1,2,……,k} như các điểm trung gian trên đường đi Bây giờ, với chức năng này, mục tiêu của chúng ta là tìm
đường đi ngắn nhất từ mỗi i cho mỗi j sử dụng bất kỳ đỉnh nào trong {1,2,
……,N}
- Đối với mỗi cặp đỉnh này, shorestPath(i,j,k) có thể là một trong hai
(1)một con đường không đi qua (chỉ sử dụng các đỉnh trong tập hợp {1,…,k-1} )
Trang 8(2) một con đường đi qua k (từ i đến k và sau đó từ k đến j, cả hai đều chỉ sử dụng các đỉnh trung gian trong {1,….k-1} )
- Chúng tôi biết rằng con đường tốt nhất từ i đến j chỉ sử dụng các
đỉnh 1 xuyên qua k-1 được định nghĩa bởi shorestPath(i,j,k-1) và rõ ràng là nếu có một con đường tốt hơn từ i đến k đến j, thì độ dài của đường dẫn này
sẽ là nối của đường đi ngắn nhất từ i đến k (chỉ sử dụng các đỉnh trung gian trong {1,….,k-1} ) và con đường ngắn nhất từ k đến j (chỉ sử dụng các đỉnh trung gian trong {1,….,k-1} )
- Nếu w(i,j) là trọng lượng của cạnh giữa các đỉnh i và j, chúng ta có thể xác định shorestPath(i,j,k) theo công thức đệ quy sau : trường hợp cơ sở là và trường hợp đệ quy là:
- Công thức này là trung tâm của thuật toán Floyd – Warshall Thuật toán hoạt động bằng máy tính đầu tiên shorestPath(i,j,k) cho tất cả (i,j) cặp cho k=1 , sau đó k=2, và như thế Quá trình này tiếp tục cho đến khi k=N và chúng tôi
đã tìm ra con đường ngắn nhất cho tất cả (i,j) các cặp sử dụng bất kỳ đỉnh trung gian nào Mã giả cho phiên bản cơ bản này như sau:
Trang 9- Thuật toán trên được thực thi trên biểu đồ bên trái phía dưới:
- Trước đệ quy đầu tiên của vòng lặp ngoài, có nhãn k = 0 ở trên, các đường dẫn duy nhất đã biết tương ứng với các cạnh đơn trong biểu đồ Tại k = 1 ,
các đường đi qua đỉnh 1 được tìm thấy: đặc biệt, đường dẫn [2,1,3] được tìm thấy, thay thế đường đi [2,3] có ít cạnh hơn nhưng dài hơn (về trọng
số ) Tại k = 2 , các đường đi qua các đỉnh {1,2} được tìm thấy Các hộp màu
đỏ và xanh lam cho biết cách đường dẫn [4,2,1,3] được lắp ráp từ hai đường dẫn đã biết [4,2] và [2,1,3] đã gặp trong các lần lặp trước, với 2 trong giao điểm Đường đi [4,2,3] không được xem xét, vì [2,1,3] là đường đi ngắn
nhất gặp từ 2 đến 3 Tại k = 3, các đường đi qua các đỉnh {1,2,3} được tìm thấy Cuối cùng, tại k = 4 , tất cả các đường đi ngắn nhất được tìm thấy.
Trang 10- Ma trận khoảng cách tại mỗi lần lặp của k , với các khoảng cách được cập
nhật được in đậm , sẽ là:
- Độ phức tạp: Để cho n là |V|, số lượng đỉnh Để tìm tất cả
n2 của shorestPath(i,j,k) (cho tất cả i và j) từ những người
của shorestPath(i,j,k-1) đòi hỏi 2n2 các hoạt động Kể từ khi chúng ta bắt đầu với shorestPath(i,j,0)=edgeCost(i.j) và tính toán trình tự của n ma trận shorestPath(i,j,1), shorestPath(i,j,2),…, shorestPath(i,j,n), tổng số hoạt động được sử dụng là n.2n2=2n3 Do đó, độ phức tạp của thuật toán là O(n3)
void floydWarshall(void ){
int i , j , k ;
for ( k = 0 ; k < n ; k ++){
for ( i 0 ; i < n ; i ++){
for ( j 0 ; j < n ; j ++ ) {
if ( A [ i ][ k ] + A [ k ]
[ j ] < A [ i ][ j ])
A [ i ][ j ] = A [ i ][ k ]
+ A [ k ][ j ];
}
} }
}
1 N+1
N*(N+1) N*N*(N+1) N*N*N
N*N*N
Trang 11Gọi T(n) là thời gian thực
hiện chương trình
T(n)= 1 + (N+1) + N*(N+1)
+ N*N*(N+1) +2* N*N*N +
5*N 2 + 3*N + 2
= 3*N 3 + 7*N 2 + 5*N + 4
=> Độ phức tạp của
void PrintMatran(void ){
cout << "Ma tran co
khoang cach ngan
nhat giua cac cap
dinh: \n" ;
for ( int i = 0 ; i < n ; i++ ){
for ( int j = 0 ; j < n ; j ++)
{
if ( A [ i ][ j ] == INF )
cout << "INF" << "
" ;
else
cout << A [ i ][ j ] <<
" " ;
}
cout << endl ;
}
}
1
N+1 N*(N+1)
N*N N*N
N*N
N*N
N
= 1 + (N+1) + N*(N+1) + 4*N*N + N
Trang 134 Hành vi có chu kì tiêu cực:
Chu kỳ âm là chu kỳ mà các cạnh của nó tổng bằng một giá trị âm Không
có đường đi ngắn nhất giữa bất kỳ cặp đỉnh nào i, j tạo thành một phần của chu kỳ tiêu cực, bởi vì độ dài đường dẫn từ i đến j có thể to nhỏ tùy ý
(âm) Đối với đầu ra có ý nghĩa số, thuật toán Floyd – Warshall giả định rằng không có chu kỳ âm nào Tuy nhiên, nếu có các chu kỳ âm, thuật toán Floyd – Warshall có thể được sử dụng để phát hiện chúng Theo trực giác thì là thế này:
Thuật toán Floyd – Warshall sửa đổi lặp đi lặp lại độ dài đường đi giữa tất cả các cặp đỉnh (i,j), bao gồm cả ở đâu i=j;
Ban đầu, chiều dài của con đường (i,j) là số không;
Một con đường [I,k,…,j] chỉ có thể cải thiện điều này nếu nó có độ dài nhỏ hơn 0, tức là biểu thị một chu kỳ âm;
Do đó, sau thuật toán, (i,j) sẽ là số âm nếu tồn tại một đường dẫn có độ dài
âm từ i Quay lại i
Do đó, để phát hiện các chu kỳ âm bằng cách sử dụng thuật toán Floyd – Warshall, người ta có thể kiểm tra đường chéo của ma trận đường dẫn và sự hiện diện của một số âm chỉ ra rằng đồ thị chứa ít nhất một chu kỳ
âm Trong quá trình thực hiện thuật toán, nếu có một chu kỳ âm, các số lớn
Trang 14theo cấp số nhân có thể xuất hiện, lớn như , Ở đâu là giá trị tuyệt đối lớn nhất của một cạnh âm trong đồ thị Để tránh các vấn đề tràn / tràn dòng, người ta nên kiểm tra các số âm trên đường chéo của ma trận đường dẫn trong vòng lặp for bên trong của thuật toán.Rõ ràng, trong một đồ thị vô hướng, một cạnh âm tạo ra một chu trình âm (tức là một bước
đi khép kín) liên quan đến các đỉnh tới của nó Coi tất cả các cạnh của đồ thị
ví dụ trên là vô hướng, ví dụ dãy đỉnh 4 - 2 - 4 là một chu trình có tổng trọng
số là −2
5 Tái tạo đường dẫn:
Trang 15Thuật toán Floyd – Warshall thường chỉ cung cấp độ dài của các đường đi giữa tất cả các cặp đỉnh Với những sửa đổi đơn giản, có thể tạo ra một phương thức
để tạo lại đường đi thực tế giữa hai đỉnh điểm cuối bất kỳ Trong khi người ta
có thể có xu hướng lưu trữ đường đi thực tế từ mỗi đỉnh đến mỗi đỉnh khác, điều này là không cần thiết, và trên thực tế, rất tốn kém về bộ nhớ Thay vào
gian sử dụng O(|V|) bộ nhớ để lưu trữ từng cây cho phép chúng tôi tạo lại một cách hiệu quả một đường đi từ hai đỉnh được kết nối bất kỳ
Mã Giả
6 Ưu nhược điểm của thuật toán Floy-Washall
Ưu điểm:
Cực kì đơn giản
Trang 16 Dể thực hiện
Nhược điểm: không có
IV ỨNG DỤNG
Thuật toán Floyd – Warshall có thể được sử dụng để giải quyết các vấn đề sau, trong số các vấn đề khác:
Đường đi ngắn nhất trong đồ thị có hướng (thuật toán Floyd)
Đóng cửa bắc cầu của đồ thị có hướng (thuật toán Warshall) Trong công thức ban đầu của Warshall về thuật toán, đồ thị không có trọng số và được biểu diễn bằng ma trận kề Boolean Sau đó, phép toán cộng được thay thế
bằng phép kết hợp logic (AND) và phép toán tối thiểu bằng phép nối
logic (OR)
Tìm một biểu thức chính quy biểu thị ngôn ngữ thông thường được chấp nhận bởi một tự động hữu hạn ( thuật toán của Kleene , một tổng quát hóa có liên quan chặt chẽ của thuật toán Floyd-Warshall)
Inversion của thực ma trận ( Gauss-Jordan thuật toán )
Định tuyến tối ưu Trong ứng dụng này, người ta quan tâm đến việc tìm đường đi với dòng chảy lớn nhất giữa hai đỉnh Điều này có nghĩa là, thay vì lấy cực tiểu như trong mã giả ở trên, thay vì lấy cực đại Các trọng số cạnh đại diện cho các ràng buộc cố định đối với luồng Trọng số đường dẫn đại diện cho các điểm nghẽn; vì vậy phép toán cộng ở trên được thay thế bằng phép toán tối thiểu
Tính toán nhanh các mạng Pathfinder
Trang 17 Đường dẫn rộng nhất / Đường dẫn băng thông tối đa
Tính toán dạng chính tắc của ma trận ràng buộc chênh lệch (DBM)
Tính toán sự giống nhau giữa các đồ thị
Wikipedia.org
123doc.net
Giáo trình môn Cấu trúc dữ liệu và giải thuật của thầy Trần Anh Tuấn
Giaithuatlaptrinh.com
Youtube: https://www.youtube.com/watch?v=eRlwaxXvly0
https://www.youtube.com/watch?v=g45sGaUaucI&t=462s