Trường ĐẠI HỌC GIAO
THƠNG VẬN TẢI
THÀNH PHỐ HỒ CHÍ MINH
Mơn: Phân tích thiết kế giải thuật-GVHD:
Trần Tuấn Anh
ủ đề: Phân tích độ phức tạp thuật to
Floyd-Warshall
Thành Viên nhóm 9:
Nguyễn Việt Long
Trần Đơng Dung
Nguyễn Trọng Nhân
THUẬT TOÁN FLOYD-WARSHALL
FLOYD-WARSHALL
1. Tìm hiểu về Floyd-Warshall
2. Code mẫu- phân tích cách hoạt động
3. Phân tích độ phức tạp giải thuật
Ý TƯỞNG
Trong những bài toán đường đi ngắn nhất mà
chúng ta cần thông tin về đường đi giữa nhiều
cặp đỉnh, ta có xu hướng là sẽ tính tốn đường
đi ngắn nhất giữa mọi cặp đỉnh.
Thuật toán Floyd-Warshall là một thuật toán
phù hợp để thực hiện tác vụ này.
KHÁI NIỆM
Thuật tốn Floyd-Warshall cịn được gọi là thuật tốn
Floyd được Robert Floyd tìm ra năm 1962. Thuật tốn
Floyd là một thuật toán giải quyết bài toán đường đi
ngắn nhất trong một đồ thị có hướng có cạnh mang
trọng số dương dựa trên khái niệm các Đỉnh Trung Gian.
Thuật toán Floyd-Warshall giúp xác định tất cả các
Đường đi ngắn nhất giữa tất cả các cặp đỉnh.
Định lý: Thuật toán Floyd-Warshall cho ta Ma trận W* =
Wn là ma trận Khoảng cách nhỏ nhất của đồ thị G.
Ma trận trọng điểm của đồ thị
Cho đồ thị:
Từ đồ thị ta chuyển thành ma trận A
Tạo một ma trận có chiều trong đó n là số đỉnh. i và j là các
đỉnh của đồ thị
Mỗi ô A [i] [j] được lấp đầy bởi khoảng cách từ đỉnh
đến đỉnh. Nếu khơng có đường đi từ đỉnh đến đỉnh, ô được để
Với k = 1
Ta có A0 ở bước trước
Các phần tử trong cột đầu tiên và hàng đầu tiên được giữ nguyên.
k la đỉnh trung gian trong đường đi ngắn nhất từ nguồn đến đích
Với k =1 là đỉnh đầu tiên, ta tính đỉnh nguồn đến đích thơng qua đỉnh k này,
A[i][j] được lấp đầy bởi:
(A[i][k] + A[k][j]) if (A[i][j] > A[i][k] + A[k][j])
Với k = 2
Tương tự, A2 được tạo bằng A1. Các phần tử
trong cột thứ hai và hàng thứ hai được giữ
nguyên.
K =3
K =4
ĐỘ PHỨC TẠP CỦA FLOYD-WARSHALL
void PrintMatran(void){
1
cout << "Ma tran: \n";
for (int i = 0; i < n; i++){
N+1
for (int j = 0; j < n; j++){N*(N+1) = 1 + (N+1) + N*(N+1)
+ 4*N*N + N
if (A[i][j] == INF)
N*N
2
=
5*N
+ 3*N + 2
N*N
cout << "INF" << "
";
N*N
else
N*N
cout << A[i][j] << " ";
}
cout << endl;
}
}
N
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++){
N*N*N
if (A[i][k] + A[k][j] < A[i][j])
N*N*N
A[i][j] = A[i][k] + A[k][j];
}
}
}
PrintMatran();
}
1
N+1
N*(N+1)
N*N*(N+1)
Gọi T(n) là thời gian
thực hiện chương trìn
T(n)= 1 + (N+1)
+ N*(N+1)
+ N*N*(N+1)
+2* N*N*N
+ 5*N2 + 3*N + 2
= 3*N3 + 7*N2 +
5*N + 4
Độ phức tạp của
thuật toán :
O(n3)
5*N2 + 3*N + 2
(Độ phức tạp không
Gian: 0(n^2) )
Ưu và Nhược điểm FloydWarshall
Ưu điểm:
Không cần chạy lại Thuật tốn (có nghĩa là có
tính kế thừa từ đường đi lẫn nhau)
Có thể chạy được với trọng số âm.
Nhược điểm: Chi phí cao O(n^3) cho mỗi cặp
đỉnh
Ứng dụng
Để tìm đường đi ngắn nhất là đồ thị có hướng
Để tìm cách đóng theo hướng bắc cầu của đồ
thị có hướng
Để tìm Nghịch đảo của ma trận thực
Để kiểm tra xem một biểu đồ vơ hướng có
phải là lưỡng phân hay không
So sánh giữa 2 thuật toán dijkstra và FloydWarshall
Dijsktra
Ưu điểm
Nhược điểm
FloydWarshall
Chi phí thấp hơn
Thuật tốn FloydWarshall
Khơng cần chạy lại
Thuật tốn (có nghĩa
là có tính kế thừa từ
đường đi lẫn nhau)Có
thể chạy được với
trọng số âm
Khơng chạy được với
trọng số âm.
Chi phí
cao {\displaystyle
O(n^{3})} cho mỗi
CODE:
Câu hỏi:
1. Thuật tốn Floyd-Warshall có độ phức tạp là
bao nhiêu?
2. Ứng dụng của thuật toán Floyd-Warshall.
3. Ưu và nhược điểm của thuật toán FloyWarshall
THANKS