Đường đi ngắn nhất trong ĐT có trọng số - iChooseFish.com
-
Upload
khangminh22 -
Category
Documents
-
view
0 -
download
0
Transcript of Đường đi ngắn nhất trong ĐT có trọng số - iChooseFish.com
Bài toán
Cho G = <V, E>. Mỗi cạnh của đồ thị được gán với
một số thực gọi là trọng số.
Bài toán: s và t là 2 đỉnh của đồ thị G . Hãy tìm đường
đi có tổng trọng số nhỏ nhất từ s đến t.
A
B
C
D
E F
G
5
3
916
22
5
3
15
17
711
Đường đi ngắn nhất từA đến D?
Ma trận trọng số
Xét đồ thị G = (V, E) với tập đỉnh V = {v1, …, vn}.
Mỗi cạnh của đồ thị được gán với một số thực gọi là
trọng số
Ma trận kề của đồ thị là ma trận Anxn xác định như sau:
𝑎𝑖𝑗 = 0 nế𝑢 𝑣𝑖𝑣𝑗 ∉ 𝐸
𝑐 nếu 𝑣𝑖𝑣𝑗 ∈ 𝐸, trọng số bằng c
Điều kiện
Để bài toán có lời giải:
Phải tồn tại đường đi từ s tới t
Đồ thị vô hướng liên thông hoặc đồ thị có hướng liên
thông mạnh
Đồ thị vô hướng, trong đó s, t thuộc một thành phần liên
thông
Đồ thị có hướng có đường đi từ s tới t
Đồ thị không chứa chu trình âm
Đồ thị vô hướng không có cạnh âm
Đồ thị có hướng không có chu trình âm
Ý tưởng
Nếu s, u2, …, uk-1, v, uk+1, …, un-1, t là đường đi ngắn
nhất từ s → t thì:
s, u2, …, uk-1, v là đường đi ngắn nhất từ s → v
v, uk+1, …, un-1, t là đường đi ngắn nhất từ v → t
⇒ mở rộng thành bài toán tìm đường đi ngắn nhất từ một
đỉnh đến tất cả các đỉnh còn lại
… …s v t
…X
Ý tưởng
Tại đỉnh cần xét, ta thử đường đi qua các đỉnh trung
gian để đến đích
Cập nhật đường đi ngắn nhất nếu tìm được đường đi
tốt hơn đường đi tốt nhất đã biết.
Thông tin cần lưu:
Độ dài đường đi ngắn nhất từ s → v đã biết
Đỉnh nằm trước v trên đường đi ngắn nhất đã biết.
Thuật toán Ford-Bellman
// Khởi tạo
for v V do{
d[v]:= a[s,v]; // khoảng cách từ s v = trọng số cung
π[v]:= s; // đỉnh trước v trên đường đi là s
}
d[s]:= 0;
// Lặp
for k:= 1 to |V|-2 do
for v V\{ s} do
for u V do
if d[v] > d[u] + a[u,v] then{
d[v]:= d[u] + a[u,v];
π[v]:= u;
}
Ví dụ
Khởi tạo
0
7
6
z
u v
x y
6
5
–3
9
7
7
8
–2
–4
2
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
Ví dụ
0
27
46
z
u v
x y
6
5
–3
9
7
7
8
–2
–42
i = 1
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 0; z 6; z 4; x 2; u 7; z
Qua u v y X
u 6, z 11, u 2, u 7, z
v 9 6, z 11, u 2, u 7, z
y 6, z 9, y 2, u 7, z
x 6, z 4, x 2, u 7, z
Ví dụ
0
27
46
z
u v
x y
6
5
–3
9
7
7
8
–2
–42
i = 2
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 0; z 6; z 4; x 2; u 7; z
2 0; z 2; v 4; x 2; u 7; z
Qua u v y x
u 6, z 4, x 2, u 7, z
v 2, v 4, x 2, u 7, z
y 2, v 4, x 2, u 7, z
x 2, v 4, x 2, u 7, z
Ví dụ
0
27
46
z
u v
x y
6
5
–3
9
7
7
8
–2
–42
i = 3
I d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 0; z 6; z 4; x 2; u 7; z
2 0; z 2; v 4; x 2; u 7; z
3 0; z 2; v 4; x -2; u 7; z
Qua u v y x
u 2; v 4, x -2, u 7, z
v 2, v 4, x -2, u 7, z
y 2, v 4, x -2, u 7, z
x 2, v 4, x -2, u 7, z
Nhận xét
Thuật toán Ford-Bellman áp dụng được cho trường
hợp không có chu trình âm trong đồ thị
Nhược điểm:
Chi phí tính toán lớn
Không thể cải tiến cho trường hợp tổng quát
Các vòng lặp thường hội tụ về kết quả sớm hơn so với
điều kiện dừng vòng lặp
Nếu đồ thị không có cạnh âm thì: giá trị nhỏ nhất của
d[i] trên mỗi hàng của ma trận F-B sẽ không thể nhỏ
hơn tính từ hàng đó về sau
Thuật toán Dijkstra
Ý tưởng:
Do đồ thị không có cạnh âm: trong mỗi bước, đỉnh có
khoảng cách nhỏ nhất (d[v] min) sẽ không thay đổi về
sau
Chọn đỉnh này là đỉnh trung gian đi đến các đỉnh còn lại
sẽ giúp đường đi có khả năng tối ưu cao hơn
Thuật toán Dijkstra// Khởi tạo
for v V do{
d[v]:= a[s,v];
π[v]:= s;
}
d[s]:= 0; T:= V\{s} ; // T là tập các đỉnh còn có thể rút ngắn đường đi
// Lặp
while T != do {
u := ;
T:= T\{u} ;
for v T do
if d[v] > d[u] + a[u,v] then{
d[v]:= d[u] + a[u,v];
π[v]:= u;
}
}
T) t td(minargt
Ví dụ
0
7
6
z
u v
x y
6
5
3
9
2
7
8
2
12
Khởi tạo
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
Ví dụ
Bước lặp 1
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 - - 11; u 7; u 7; z
0
77
116
z
u v
x y
6
5
3
9
2
7
8
2
12
Ví dụ
Bước lặp 2
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 - - 11; u 7; u 7; z
2 - - 11; u - 7; z
0
77
116
z
u v
x y
6
5
3
9
5
7
8
2
12
Ví dụ
Bước lặp 3
i d[z];π[z] d[u]; π[u] d[v];π[v] d[y];π[y] d[x];π[x]
0; z 6; z ∞; z ∞; z 7; z
1 - - 11; u 7; u 7; z
2 - - 11; u - 7; z
3 - - 10; x - -
0
7
6
z
u v
x y
6
5
3
9
5
7
8
2
12
Thuật toán Floyd
Đường đi ngắn nhất giữa tất cả các cặp đỉnh?
Thuật toán Floyd dựa trên ý tưởng:
Tất cả các đường đi con của đường đi ngắn nhất là ngắn
nhất
Giả sử ma trận D = [dij](k) là đường đi ngắn nhất từ i đến j
chỉ đi qua các đỉnh trung gian 1, 2, …, k
=> Kết quả của bài toán sẽ là [dij](n)
Thuật toán Floyd
Xác định dij(k):
dij(0) = a[i, j]
k > 0:
dij(k) = min (dij
(k-1); dik(k-1) + dkj
(k-1))
Thuật toán Floyd
Xác định đường đi bằng ma trân đỉnh trước cuối của
đường đi
π[i, j] = Đỉnh cuối cùng trên đường đi ngắn nhất từ i
đến j
Khởi tạo: π[i, j] = I
Tại mỗi bước lặp: xác định xem dùng đỉnh k có làm rút
ngắn đường đi từ i đến j không?
Nếu có:
Lưu lại trọng số của đường đi mới – ngắn hơn – từ i đến j
Lưu lại thông tin về việc thay đổi đường đi để đi qua k
Thuật toán Floyd Lưu lại thông tin về việc thay đổi đường đi để đi qua k
=> π[i, j] = π[k, j]
Thay đổi thông tin:
If (d[i, j] > d[i, k] + d[k, j]) then
Begin
d[i, j]:= d[i, k] + d[k, j];
π[i, j]:= π[k, j];
End
Thuật toán Floyd// Khởi tạo
For i:= 1 to n do
For j:= 1 to n do
Begin
d[i, j]:= a[i, j]; π[i, j]:= i;
End;
// Bước lặp
For i:= 1 to n do
For i:= 1 to n do
For j:= 1 to n do
If (d[i, j] > d[i, k] + d[k, j]) then
Begin
d[i, j]:= d[i, k] + d[k, j];
π[i,j]:= π[k,j];
End;