Chương 2: CÁC THUẬT TOÁN TỐI ƯU TRÊN MÔ HÌNH ĐỒ THỊ
2.2 Mô hình các bài toán tối ưu
2.2.2 Bài toán xác định đường đi ngắn nhất
Cho đơn đồ thị G = (V, E) lên thông, có trọng số dương,
1, 2,..., n, 1, 2,..., m
V v v v E e e e . Mỗi cạnh eij ( ,v vi j) được gán với một trọng số dương Cij xác định như sau:
- Cij nếu ( ,v vi j)E - Cij0 nếu vi vj
- Cij= trọng số thực nếu ( ,v vi j)E
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn
Yêu cầu: Tìm đường đi ngắn nhất từ một đỉnh nguồn tới các đỉnh còn lại của đồ thị
2.2.2.1 Đường đi ngắn nhất từ một đỉnh nguồn tới các đỉnh Tư tưởng của thuật toánDijkstra:
- Ta xây dựng một tập S các đỉnh mà độ dài đường đi từ gốc tới nó là ngắn nhất. Lúc đầu S chỉ chứa đỉnh gốc giả sử là a, ở mỗi bước ta thêm vào S một trong số các đỉnh còn lại của v mà độ dài từ a đến v là ngắn nhất.
- Dựng mảng Dộờở2..nựỳỷ, trong đú D uộ ựờ ỳở ỷ để ghi độ dài đường đi ngắn nhất hiện thời từ a tới đỉnh u.
- Ban đầu vỡ S chỉ chứa a, nờn D u ộ ựờ ỳở ỷ = C a, uộờở ựỳỷ. Tại mỗi bước ta sẽ chọn đỉnh
\
v V S mà D vộ ựờ ỳở ỷ là nhỏ nhất và thờm v vào S. Sau khi thờm v vào S ta xỏc định lại các D ué ù
ờ ỳở ỷvới uS. Nếu độ dài đường đi đặc biệt qua đỉnh v (vừa được chọn) mà nhỏ hơn D ué ù
ờ ỳở ỷthỡ ta lấy D uộ ự
ờ ỳở ỷlà độ dài đường đi đú.
Khi S = V thỡ D uộ ựờ ỳở ỷlưu độ dài ngắn nhất từ 1 đến u.
- Sử dụng mảng P 2..nộờở ựỳỷ trong đú P u ộ ự =ờ ỳở ỷ vnếu v là đỉnh kề trước của u. Thuật toán Dijksta
Input: Ma trận trọng số C (dương) của đồ thị với đỉnh gốc là a.
Output: Khoảng cách từ gốc a tới các đỉnh của đồ thị
Procedure Dijkstra;
Begin
S:= {a} ; D[a]:=0;
{S: Là tập các đỉnh có độ dài ngắn nhất đến gốc}
{D[a]: Là độ dài từ gốc đến đỉnh a}
For u (V {a}) do
{u: Các đỉnh còn lại của đồ thị trừ đỉnh gốc}
{V: Là tập các đỉnh của đồ thị}
Begin
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn
D[u]:= C[a,u] ;
{D[u]: Mảng lưu độ dài ngắn nhất từ gốc tới u}
{C[a,u]: Giá trị trọng số thực từ a đến u}
P[u]:= a ;
{P[u]: Là ma trận lưu vết đường đi}
End ; While V S\ do
Begin
Chọn đỉnh v trong V\S mà D[v] nhỏ nhất;
S:= S {v} ; {thêm v vào S}
For mỗi đỉnh u trong V\S do
If D[v] + C[v,u] < D[u] then Begin
D[u]:= D[v] + C[v,u];
P[u]:= v ; End;
End ; End ;
2.2.2.2 Thuật toán Folyd
Để tìm đường đi ngắn nhất giữa mọi cặp đỉnh ta có thể sử dụng thuật toán Dijkstra với các đỉnh được chọn làm nguồn lần lượt là 1, 2, …, n. Ngoài ra còn có cách trực tiếp giải quyết vấn đề trên, đó là thuật toán Floyd.
Tư tưởng của thuật toán:
- Nếu đỉnh k nằm trên đường đi ngắn nhất từ đỉnh i tới j thì đoạn đường từ i tới k và từ k tới j phải là đường đi ngắn nhất từ i tới k và từ k tới j tương ứng.
- Do đó sử dụng ma trận A để lưu độ dài đường đi ngắn nhất giữa mọi cặp đỉnh.
- Ban đầu ta đặt A i, jộ ựờ ỳở ỷ= C i, jộ ựờ ỳở ỷ, tức là ban đầu A chứa độ dài đường đi trực tiếp (không đi qua các đỉnh nào cả).
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn
- Sau đó thực hiện n lần lặp, sau lần lặp thứ k ma trận A sẽ chứa độ dài đường đi ngắn nhất giữa mọi cặp đỉnh chỉ qua cỏc đỉnh thuộc tập {1, 2, ẳ, k}. Như vậy, sau n lần lặp ta nhận được ma trận A chứa độ dài các đường đi ngắn nhất giữa mọi cặp đỉnh của đồ thị.
- Ký hiệu Aklà ma trận A sau lần lặp thứ k, tức là A i, jk ộ ựờ ỳở ỷlà độ dài đường đi ngắn nhất từ i đến j chỉ qua cỏc đỉnh thuộc {1, 2,ẳ, k}. A i, jk ộ ựờ ỳở ỷđược tớnh theo cụng thức như sau:
{ }
k k 1 k 1 k 1
A i, j ộ ựờ ỳở ỷ = Min A - ộ ựờ ỳở ỷi, j , A- ộ ựờ ỳở ỷi, k + A - ộ ựờ ỳở ỷk, j
- Trong quá trình lặp ta phải lưu lại vết đường đi tức là các đường đi ngắn nhất đi qua cỏc đỉnh nào. Khi đú ta sẽ sử dụng mảng phụ P n n[ ], trong đú P i, jộ ựờ ỳở ỷlưu đỉnh k nếu đường đi ngắn nhất từ i tới j qua đỉnh k. Ban đầu p i, jộ ự=ờ ỳở ỷ 0với mọi i, j, vỡ lúc đó đường đi ngắn nhất là đường đi trực tiếp, không qua các đỉnh nào cả.
Với các phần tử như trên ta thấy ở bước lặp thứ k thì giá trị của ma trận A ở dòng thứ k và cột thứ k là không thay đổi.
Thuật toán:
Procedure Floyd;
Var i, j, k: integer;
Begin
For i:=1 to n do For j:=1 to n do Begin
A[i,j]:= C[i,j];
P[i,j]:= 0;
End;
For k:= 1 to n do For i:=1 to n do For j:=1 to n do
Số hóa bởi Trung tâm Học liệu – Đại học Thái Nguyên http://www.lrc-tnu.edu.vn
If A[i,k] + A[k,j] < A[i,j] then
Begin
A[i,j]:= A[i,k] + A[k,j];
P[i,j]:= k;
End;
End;