Download as pdf or txt
Download as pdf or txt
You are on page 1of 56

ĐỒ THỊ 3

Bài toán đường đi ngắn nhất


Thuật toán Ford-Bellman
Thuật toán Dijkstra
Thuật toán Floyd

Đường đi ngắn nhất 1


Bài toán đường đi ngắn nhất

■ Đồ thị có trọng số là đồ thị mà mỗi cạnh (i,j) của nó


được gán một số thực A(i,j) gọi là trọng số của cạnh.
■ Ta quy ước A(i,j) = ∞, nếu (i,j) không thuộc E. A(i,i) = 0
với mọi i.
■ Cho một đường đi trên G. Độ dài đường đi là tổng
trọng số của các cạnh trên đường đi đó.

Đường đi ngắn nhất 2


Bài toán đường đi ngắn nhất

■ Đường đi: A B E M
■ Chiều dài: (A, B) + (B, E) + (E, M) = 12 + 9 + 26 = 57

Đường đi ngắn nhất 3


Bài toán đường đi ngắn nhất

■ Bài toán: Cho đồ thị có trọng số G = (V, E). Hai đỉnh s, t


thuộc V. Tìm đường đi ngắn nhất giữa s và t.

■ Xét đường đi: A H G M

Đường đi ngắn nhất 4


Bài toán đường đi ngắn nhất

■ Nhận xét: Nếu đường đi A H G M là đường đi ngắn


nhất thì mọi đường đi con của nó cũng là đường đi
ngắn nhất
■ A H G; H G M đều là đường đi ngắn nhất

Đường đi ngắn nhất 5


Bài toán đường đi ngắn nhất

■ Giả sử cần tìm đường đi ngắn nhất giữa hai đỉnh s và t


và đồ thị không có chu trình âm.
■ Gọi D[s,t] là khoảng cách từ s đến t. Quy ước nếu không
có đường đi từ s đến t thì D[s,t] = ∞.
■ Để tìm đường đi ngắn nhất từ s tới t, ta có thể thấy
rằng luôn có một đỉnh t1 khác t sao cho:
D[s,t]=D[s,t1] + A[t1,t]
Công thức trên có ý nghĩa là: trong đường đi ngắn nhất từ
s đến t, ta trước tiên đi từ s tới t1 sau đó đi từ t1 đến t theo
cạnh (t1,t).

Đường đi ngắn nhất 6


Bài toán đường đi ngắn nhất

S t

Đường đi ngắn nhất 7


Bài toán đường đi ngắn nhất

D(s,t1)
t1 A(t1,t)

S t

Đường đi ngắn nhất 8


Bài toán đường đi ngắn nhất

D(s,t1)
t1 A(t1,t)

S t
Đi theo một đường đi ngắn nhất từ S đến t1

Đường đi ngắn nhất 9


Bài toán đường đi ngắn nhất

Rồi theo cạnh t1 đến t


D(s,t1)
t1 A(t1,t)

S t
Đi theo một đường đi ngắn nhất từ S đến t1

Đường đi ngắn nhất 10


Bài toán đường đi ngắn nhất

■ Sau đây chúng ta sẽ xét qua 3 thuật toán cơ bản:


– Thuật toán Ford – Bellman: tìm đường đi ngắn nhất
giữa đỉnh s với tất cả các đỉnh của đồ thị.
– Thuật toán Dijkstra: tìm đường đi ngắn nhất giữa đỉnh s
với tất cả các đỉnh của đồ thị.
– Thuật toán Floyd: tìm đường đi ngắn nhất giữa mọi cặp
đỉnh của đồ thị
■ Các thuật toán đều dựa vào tư tưởng đã nói ở phía
trước

Đường đi ngắn nhất 11


Thuật toán Ford-Bellman

Tìm đường đi ngắn nhất giữa đỉnh s với tất cả các đỉnh
của đồ thị.
■ Gọi D[v] là khoảng cách đường đi ngắn nhất từ s tới v.
Khởi tạo:
 D[v]= +∞ với v khác s
 D[s]=0
■ Ta tiến hành tối ưu hóa D[v] như sau:
Xét mọi cặp đỉnh (u, v) nếu thỏa mãn:
D[v]>D[u]+A[u, v]
thì ta sẽ gán lại D[v]=D[u]+A[u, v].
■ Thuật toán sẽ kết thúc khi không còn tối ưu thêm được
một đỉnh nào nữa.
Đường đi ngắn nhất 12
Thuật toán Ford-Bellman

do
Stop = false;
for (u ∈ V) do
for (v ∈ V do)
if (d[v] > d[u]+A[u, v])
{
d[v] = d[u]+A[u,v];
Truoc[v] = u; {Lưu trữ đường đi}
Stop:=true;
};
while Stop;

Đường đi ngắn nhất 13


Thuật toán Ford-Bellman

Tính đúng đắn


■ Tại bước khởi tạo: D[v] = ∞. Đây là đường đi ngắn nhất
từ s tới v qua không quá 0 cạnh.
■ Giả sử khi bắt đầu bước lặp thứ i, D[v] đã bằng độ dài
đường đi ngắn nhất từ s tới v qua không quá i-1 cạnh.

Đường đi ngắn nhất 14


Thuật toán Ford-Bellman

■ Do đó đường đi ngắn nhất từ s tới v qua không quá i cạnh


phải được thành lập bằng cách lấy tối ưu giữa hai giá trị:
– Độ dài đường đi ngắn nhất từ s tới v qua không quá i-1 cạnh.

– Độ dài đường đi ngắn nhất từ s tới u qua không quá i-1 cạnh
cộng với trọng số cạnh (u,v).
■ Theo cách lý luận trên, sau khi lặp n-1 thì ta sẽ có đường đi
từ s tới v qua không quá n-1 cạnh.
■ Do không có chu trình âm nên đường đi ngắn nhất từ s tới v
không quá n-1 cạnh. Do đó ta đã tìm được đường đi.

Đường đi ngắn nhất 15


Thuật toán Ford-Bellman

12
1 30
5
2
4 12
13 21
1
4
3

Đường đi ngắn nhất 16


Thuật toán Ford-Bellman
0
∞ ∞
12
1 30
5
2
4 12
13 21 ∞
∞ 1
4
3

Khởi tạo: D[i]=∞, D[s]=0

Đường đi ngắn nhất 17


Thuật toán Ford-Bellman
0
∞ ∞
12
1 30
5
2
4 12
13 21 ∞
∞ 1
4
3

Lần lặp 1: đđ ngắn nhất từ 1 đến i


qua không quá 1 cạnh.
Đường đi ngắn nhất 18
Thuật toán Ford-Bellman
0
12 ∞
12
1 30
5
2
4 12
13 21 ∞
13 1
4
3

Lần lặp 1: đđ ngắn nhất từ 1 đến i


qua không quá 1 cạnh.
Đường đi ngắn nhất 19
Thuật toán Ford-Bellman
0
12 ∞
12
1 30
5
2
4 12
13 21 ∞
13 1
4
3

Lần lặp 2: đđ ngắn nhất từ 1 đến i


qua không quá 2 cạnh.
Đường đi ngắn nhất 20
Thuật toán Ford-Bellman
0
12 42
12
1 30
5
2
4 12
13 21 14
13 1
4
3

Lần lặp 2: đđ ngắn nhất từ 1 đến i


qua không quá 2 cạnh.
Đường đi ngắn nhất 21
Thuật toán Ford-Bellman
0
12 42
12
1 30
5
2
4 12
13 21 14
13 1
4
3

Lần lặp 3: đđ ngắn nhất từ 1 đến i


qua không quá 3 cạnh.
Đường đi ngắn nhất 22
Thuật toán Ford-Bellman
0
12 26
12
1 30
5
2
4 12
13 21 14
13 1
4
3

Lần lặp 3: đđ ngắn nhất từ 1 đến i


qua không quá 3 cạnh.
Đường đi ngắn nhất 23
Thuật toán Ford-Bellman
0
12 26
12
1 30
5
2
4 12
13 21 14
13 1
4
3

Đường đi ngắn nhất 24


Thuật toán Ford-Bellman

Nhận xét:
■ Thuật toán Ford-Bellman tối ưu hóa D[i] bằng cách so
sánh với D[u] theo công thức:
D[i]=min(D[i],D[u]+A[u,i])
■ Dễ thấy, nếu tại bước này, D[u] chưa được tối ưu hoàn
toàn, thì sau này, khi D[u] được tối ưu, ta lại phải tiến
hành tối ưu lại D[i].
■ Để tối ưu hơn, khi cần tối ưu hóa D[i] ta chỉ dùng
những đỉnh u mà D[u] không thể tối ưu hơn được nữa.
Đó chính là cách thức hoạt động của thuật toán
Dijkstra dưới đây.

Đường đi ngắn nhất 25


Thuật toán Dijkstra

■ Tìm đường đi ngắn nhất giữa đỉnh s và các đỉnh còn lại.
■ Giả sử ta đã có đường đi ngắn nhất (từ A đến F):
ABCDEF
■ Khi đó, AB, ABC, ABCD … cũng đều là đường đi ngắn
nhất.
■ Để ý quá trình lặp của thuật toán Ford-Bellman, sau
bước lặp thứ i, ta sẽ có độ dài đường đi ngắn nhất từ s
qua đỉnh v nào đó không quá i đỉnh.

Đường đi ngắn nhất 26


Thuật toán Dijkstra

■ Giả sử ta đã có đường đi ngắn nhất (từ A đến F):


ABCDEF
■ Khi đó, AB, ABC, ABCD … cũng đều là đường đi ngắn
nhất.
■ Do nhận xét ở trên thì mỗi vòng lặp i, ta sẽ có một
đường đi ngắn nhất từ s tới một đỉnh u, và đường đi đó
không tối ưu được nữa.

Đường đi ngắn nhất 27


Thuật toán Dijkstra

■ Do đó, để đẩy nhanh quá trình tình toán, tại mỗi lần
lặp, ta lưu lại các đỉnh không thể tối ưu được nữa và
dùng các đỉnh đó để tối ưu các đỉnh khác.
Tìm đường đi ngắn nhất từ s đến f
■ Thuật toán được mô tả như sau:
– Mỗi đỉnh i sẽ được gán 2 nhãn:
■ Nhãn thứ nhất là Check[i]. Check[i]=0 nếu D[i] còn có
thể tối ưu được. Check[i]=1 nếu D[i] không thể tối ưu
được nữa.
■ Nhãn thứ hai là giá trị D[i].

Đường đi ngắn nhất 28


Thuật toán Dijkstra

Bước 1: khởi tạo (đường đi ngắn nhất từ s tới đỉnh v bất kỳ qua
không quá 0 cạnh)
D[v]= +∞; D[s]=0;
Check[v]=0;
Bước 2: lặp, gồm hai thao tác:
■ Cố định nhãn: Tìm đỉnh u sao cho D[u] không thể tối ưu được
nữa: đỉnh u như thể là đỉnh u có D[u] nhỏ nhất trong tất cả các
đỉnh còn có thể tối ưu được (các đỉnh có Check[u]=0).
Kết nạp u vào đỉnh không thể tối ưu được nữa (Check[u]=1)
■ Sửa nhãn: Dùng đỉnh u để tối ưu các đỉnh còn có thể tối ưu được
Đối với các đỉnh v còn có thể tối ưu được (Check[v]=0), ta dùng đỉnh u
để tối ưu bằng công thức:
D[v]=min{D[v],D[u]+A[u,v]}
■ Lặp cho đến khi tất cả các đỉnh được gán nhãn hoặc đã tìm đến
đích hoặc không tồn tại đường đi thì dừng lại.
Đường đi ngắn nhất 29
Thuật toán Dijkstra

Void Dijkstra() {
Với mọi i, D[i]=oo, Check[i]=0, Trace[i]=i;
D[s]=0; Check[s] = 1;
Do
Tìm u có Check[u]=0 và D[u] nhỏ nhất
Check[u]=1;
Nếu (u == 0) hoặc (u==f) break;
Với các đỉnh v kề với u có Check[v]=0,
Nếu D[v]<D[u]+a[u,v] thì:
 gán lại D[v]=D[u]+a[u,v];
 trace[v]=u;
while true;
}
Đường đi ngắn nhất 30
Thuật toán Dijkstra

12
1 2
30
5
4 12
13 21
1
4
3

Đường đi ngắn nhất 31


Thuật toán Dijkstra

12
1 2
30
5
4 12
13 21
1
4
3

Khởi tạo: gán nhãn cho các đỉnh


Đường đi ngắn nhất 32
Thuật toán Dijkstra

Check: 0 Check: 0
Check: 0
D: 0 D: ∞
D: ∞
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: ∞

Khởi tạo: gán nhãn cho các đỉnh


Đường đi ngắn nhất 33
Thuật toán Dijkstra

Check: 0 Check: 0
Check: 0
D: 0 D: ∞
D: ∞
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: ∞
Lặp lần 1:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 34
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 0
D: 0 D: ∞
D: ∞
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: ∞
Lặp lần 1:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 35
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 0
D: 0 D: ∞
D: ∞
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: ∞
Lặp lần 1:
Tìm đỉnh không tối ưu được nữa
Dùng đỉnh đó để tối ưu các đỉnh
Đường đi ngắn nhất 36
khác
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 0
D: 0 D: ∞
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: 13
Lặp lần 1:
Tìm đỉnh không tối ưu được nữa
Dùng đỉnh đó để tối ưu các đỉnh
Đường đi ngắn nhất 37
khác
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 0
D: 0 D: ∞
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: 13
Kết thúc lần lặp 1, ta được độ dài đường đi
ngắn nhất từ s tới v qua không quá 1 cạnh
Đường đi ngắn nhất 38
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 0
D: 0 D: ∞
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: 13
Lặp lần 2:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 39
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: ∞
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: 13
Lặp lần 2:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 40
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: ∞
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: ∞
D: 13
Lặp lần 2:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 41
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: 16
D: 13
Lặp lần 2:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 42
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 0 D: 16
D: 13
Lặp lần 3:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 43
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 1 D: 16
D: 13
Lặp lần 3:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 44
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 1 D: 16
D: 13
Lặp lần 3:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 45
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 1 D: 14
D: 13
Lặp lần 3:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 46
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 0
Check: 1 D: 14
D: 13
Lặp lần 4:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 47
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13
Lặp lần 4:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 48
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 42
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13
Lặp lần 4:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 49
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 26
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13
Lặp lần 4:
Tìm đỉnh không tối ưu được nữa
Tối ưu các đỉnh còn lại 50
Đường đi ngắn nhất
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 26
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13
Lặp lần 5:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 51
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 26
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13
Lặp lần 5:
Tìm đỉnh không tối ưu được nữa
Đường đi ngắn nhất 52
Thuật toán Dijkstra

Check: 1 Check: 0
Check: 1
D: 0 D: 26
D: 12
12
1 2
30
5
4 12
13 21
1
4
3
Check: 1
Check: 1 D: 14
D: 13 Lặp lần 5:
Tất cả các đỉnh đã được đánh dấu
Thuật toán kết thúc.
Đường đi ngắn nhất 53
Thuật toán Floyd

■ Tìm đường đi ngắn nhất giữa mọi cặp đỉnh


■ Gọi D[i,j] là độ dài đường đi ngắn nhất từ đỉnh i đến
đỉnh j.
■ Ta tiến hành cực tiểu D[i,j] theo các đỉnh k xét theo thứ
tự từ 1 … n bằng công thức:
D[i,j]=min{D[i,j],D[i,k]+D[k,j]}

Đường đi ngắn nhất 54


Thuật toán Floyd

■ Thuật toán sẽ được trình bày như sau


for k:=1 to n do
for i:=1 to n do
for j:=1 to n do
D[i,j]=min{D[i,j], D[i,k]+D[k,j]}
■ Ta sẽ xét tính đúng đắn của thuật toán

Đường đi ngắn nhất 55


Thuật toán Floyd

■ Gọi Dk[i,j] là độ dài đường đi ngắn nhất từ i tới j mà


chỉ đi qua các đỉnh trung gian thuộc tập {1,..,k}.
■ Dễ thấy D0[i,j]=A[i,j] là đường đi trực tiếp.
■ Giả sử đã tính được D(k-1)[i,j], ta tiến hành xây dựng
Dk[i,j] bằng cách lầy tối ưu hai trường hợp
– Đường đi ngắn nhất không đi qua k:
Dk[i,j]=D(k-1)[i,j]
– Đường đi ngắn nhất có đi qua k:
Dk[i,j]=D(k-1)[i,u]+D(k-1)[u,j].
■ Khi k chạy đến n ta sẽ có đường đi ngắn nhất từ i, tới j
qua {1..n} đỉnh.

Đường đi ngắn nhất 56

You might also like