Professional Documents
Culture Documents
Chuong3 GraphTheory New
Chuong3 GraphTheory New
1
Nội dung
2
1. Giải thuật Warshall và giải thuật Floyd
3
Giải thuật Warshall
Có một giải thuật đơn giản để tính bao đóng truyền của
một đồ thị được biểu diễn bằng ma trận kế cận.
for y : = 1 to V do
for x : = 1 to V do
if a[x, y] then
for j: = 1 to V do
if a[y, j] then a[x, j]: = true;
Qui ước: Các phần tử trên đường chéo chính của ma trận kề bằng 0.
5
Giải thích giải thuật Warshall
Giải thuật Warshall lặp V bước trên ma trận kế cận a, tạo ra
một loạt những ma trận:
a(0),.., a(y-1),a(y),…,a(V) (3.1)
Ý tưởng chính của giải thuật là ta có thể tính tất cả các phần
tử trong mỗi ma trận a(y) từ ma trận đi trước nó a(y-1) trong loạt
ma trận (3.1)
Sau bước lặp thứ y, a[x, j] sẽ bằng 1 nếu và chỉ nếu có bất kỳ
lối đi nào từ đỉnh x đến đỉnh j với những đỉnh trung gian mang
chỉ số không lớn hơn y. Nghĩa là, x và j có thể là bất kỳ đỉnh
nào nhưng những đỉnh trung gian trên lối đi phải có chỉ số
nhỏ hơn hay bằng y.
Tại bước lặp thứ y, ta tính các phần tử của ma trận a bằng
công thức sau:
ay[x,j] = ay-1[x,j] or (ay-1[x, y] and ay-1[y, j]) (3.2)
Chỉ số y chỉ trị của một phần tử trong ma trận a sau bước lặp
thứ y.
6
a b c d
a 0 1 0 0
Thí dụ : A =
(0)
b 0 0 0 1
c 0 0 0 0
d 1 0 1 0
a b c d
a b a 0 1 0 0
A =
(1)
b 0 0 0 1
c 0 0 0 0
d 1 1 1 0
a b c d
a 0 1 0 1
c d A =
(2)
b 0 0 0 1
c 0 0 0 0
d 1 1 1 1
a b c d
a 0 1 0 1
Hình 3.2 Đồ thị có hướng và A =
(3)
b 0 0 0 1
c 0 0 0 0
diễn tiến của giải thuật Warshall d 1 1 1 1
1 D E J K
5 2
F 3
2
L M
1
8
Giải thuật Floyd
for y : = 1 to V do
for x : = 1 to V do
if a [x, y] > 0 then
for j: = 1 to V do
if a [y, j] > 0 then
if (a[x, j] = 0) or (a[x, y] + a[y, j] < a[x, j])
then
a[x, j] = a[x, y] + a[y, j];
9
Một thí dụ dùng giải thuật Floyd (cho đồ thị hình 5.7)
Ma trận trọng số
khởi đầu của
a b c d giải thuật Floyd
a 0 3
b 2 0 2
c 7 0 1 a b
d 6 0 7
3 6
c d
Hình 3.4 Đồ thị có hướng và 1
trọng số và ma trận trọng số
Qui ước: Các phần tử trên đường chéo chính của ma trận trọng số
bằng 0.
10
a b c d Ma trận trọng số
a 10 10 3 4 ứng với bước cuối
R(4) = b 2 12 5 6 của giải thuật Floyd
c 7 7 10 1
d 6 16 9 10 2
a b
7
3 6
a b c d 13
a 10 10 3 4
Cải tiến giải thuật Floyd
Ta thường muốn biết lối đi ngắn nhất từ một đỉnh đến một
đỉnh khác bao gồm những đỉnh trung gian nào.
Một cách để thực hiện điều này là dùng thêm một ma trận P,
với P[i,j] chứa đỉnh k mà khiến giải thuật Floyd tìm được giá
trị nhỏ nhất cho a[i,j].
Giải thuật Floyd cải tiến sẽ như sau:
for i := 1 to V do
for j:= 1 to V do
P[i,j] := 0;
for i := 1 to V do
a[i,i]:= 0;
14
for y : = 1 to V do
for x : = 1 to V do
if a [x, y] > 0 then
for j: = 1 to V do
if a [y, j] > 0 then
if (a[x, j] = 0) or (a[x, y] + a[y, j] < a [x, j]) then
begin
a[x, j] = a[x, y] + a[y, j];
P[x,j] := y;
end
15
a b c d
Thí dụ: R =
(0)
a
b
3
2
0000
P = 0000
(0)
c 7 1 0000
2 d 6 0000
a b a b c d
a 3 0000
R =
(1)
b 2 5 P =00a0
(1)
7
3 6 c 7 1 0000
d 6 9 00a0
a b c d
c d a 3 0000
1
R =
(2)
b 2 5 P =00a0
(2)
c 9 7 12 1 b0b0
d 6 9 00a
0
a b c d
a 12 10 3 4 cc0c
R(3) = b 2 12 5 6 P = 0 c a c
(3)
c 9 7 12 1 b0b0
Hình 3.6 Đồ thị có hướng và d 6 16 9 10 0cac
trọng số và diễn tiến của giải a b c d
thuật Floyd cải tiến a 10 10 3 4 dc0
c
R =
(4)
b 2 12 5 6 P(4)= 0 c a c
c 7 7 10 1 d0d
0
d 6 16 9 10 0ca
c 16
2. Hàng đợi có độ ưu tiên
Hàng đợi có độ ưu tiên (a priority-queue) là cấu
trúc dữ liệu mà hỗ trợ ít nhất hai tác vụ:
thêm một phần tử mới vào cấu trúc
Tìm phần tử có độ ưu tiên lớn nhất và xóa bỏ phần tử
có độ ưu tiên lớn nhất
17
Thi công hàng đợi có độ ưu tiên
này thì đơn giản khi thêm vào một phần tử mới nhưng
khi xóa bỏ phần tử có độ ưu tiên lớn nhất ra khỏi hàng
đợi thì độ phức tạp sẽ cao.)
2. Dùng cấu trúc dữ liệu heap. (Xem Phụ Lục C)
18
3. Giải thuật Dijkstra
Bây giờ chúng ta xem xét bài toán các lối đi ngắn nhất từ
một đỉnh nguồn (single source shortest paths problem). Cho
một đồ thị có hướng có trọng số với một đỉnh được xem là
đỉnh nguồn, tìm tất cả những lối đi ngắn nhất từ đỉnh nguồn
đến tất cả những đỉnh còn lại.
Giải thuật nổi tiếng để giải bài toán này là giải thuật Dijkstra.
trong đồ thị dựa vào thứ tự của khoảng cách giữa các đỉnh
này với đỉnh nguồn.
Lưu ý: Giải thuật Dijkstra áp dụng cho đồ thị có hướng có
trọng số và cả đồ thị vô hướng có trọng số.
19
Ý tưởng của giải thuật Dijkstra
Trước tiên, giải thuật tìm lối đi ngắn nhất từ đỉnh nguồn đến một
đỉnh gần với nó nhất, rồi đến đỉnh gần thứ nhì với nó, và cứ thế.
Trong trường hợp tổng quát, trước khi lượt lặp thứ i bắt đầu,
giải thuật đã xác định được những lối đi ngắn nhất từ đỉnh
nguồn đến i - 1 đỉnh gần với đỉnh nguồn nhất. Những đỉnh này,
đỉnh nguồn và những cạnh làm thành những lối đi ngắn nhất
đến chúng tạo thành một cây con Ti trong đồ thị đã cho.
Vì tất cả các cạnh trong đồ thị đều có trọng số không âm nên
đỉnh kế tiếp gần nhất đối với đỉnh nguồn sẽ nằm trong số
những đỉnh kế cận với những đỉnh trong cây Ti.
Tập hợp những đỉnh kế cận với những đỉnh trong cây Ti được
gọi là những đỉnh vùng biên (fringe vertex) làm thành một tập
đỉnh ứng viên để giải thuật chọn đỉnh kế tiếp gần nhất với đỉnh
nguồn.
20
Ý tưởng của giải thuật Dijkstra (tt.)
Để nhận dạng đỉnh gần nhất thứ i, với mỗi đỉnh vùng biên y, giải
thuật tính tổng của khoảng cách từ đỉnh y đến đỉnh x gần nhất
với nó mà thuộc về cây Ti (cho bởi trọng số cạnh (x, y)) và chiều
dài p1 của lối đi ngắn nhất từ đỉnh nguồn đến đỉnh x và chọn ra
đỉnh nào có tổng này nhỏ nhất. Việc so sánh chiều dài của
những lối đi như vậy là trọng tâm của giải thuật Dijkstra.
S: tập đỉnh đã
được xử lý, làm
thành cây con Ti
23
Q: hàng đợi có thứ tự ưu tiên
Ban đầu các mảng d và q như sau:
Q V1 V2 V3 V4 V5 V6 V7
d 0
p nil nil nil nil nil nil nil
Chọn V1 và các mảng d và p trở thành:
Q V2 V3 V4 V5 V6 V7
d 2 1
p V1 nil V1 nil nil nil
Chọn V4 và các mảng d và p trở thành:
Q V2 V3 V5 V6 V7
d 2 3 3 9 5
p V1 V4 V4 V4 V4
Chọn V2 và các mảng d và p trở thành:
Q V3 V5 V6 V7
d 3 3 9 5
p V4 V4 V4 V4 24
Chọn V3 và các mảng d và p trở
thành:
Q V5 V6 V7
d 3 8 5
p V4 V3 V4
Chọn V5 và các mảng d và p trở
thành:
Q V6 V7
d 8 5
p V3 V4
Chọn V7 và các mảng d và p trở
thành: Tóm lại: lối đi ngắn nhất từ V1 đến V2 = 2 (V1 – V2);
Q V6 từ V1 đến V3 = 3 (V1 - V4 - V3) ; từ V1 đến V4 = 1 (V1 – V4);
d 6 từ V1 đến V5 = 3 (V1 - V4 - V5);
p V7 từ V1 đến V6 = 6 (V1 - V4 - V7 -V6);
từ V1 đến V7 = 5 (V1 - V4 - V7).
Chọn V6
25
4. Giải thuật Bellman-Ford
Giải thuật Bellman-Ford giải được bài toán tìm những đường
đi ngắn nhất từ một đỉnh nguồn mà trong đó trọng số của các
cạnh có thể âm.
Cho một đồ thị có hướng có trọng số G = (V, E) với đỉnh
nguồn s và hàm trọng số w: E R, giải thuật Bellman-Ford
sẽ trả về một giá trị bool cho biết có tồn tại một chu trình với
tổng trọng số âm mà đến được từ đỉnh nguồn không. Nếu
tồn tại một chu trình như vậy, giải thuật thông báo rằng bài
toán vô nghiệm. Nếu không tồn tại một chu trình như vậy, giải
thuật cung cấp lời giải của bài toán.
Cũng giống như giải thuật Dijkstra, giải thuật Bellman-Ford sử
dụng hai mảng d và p.
Giải thuật Bellman-Ford được mô tả như sau:
26
Mã giả của giải thuật Bellman-Ford được cho như sau:
procedure Bellman-Ford(G, w, s);
/* G là đồ thị, w là hàm trọng số và s là đỉnh nguồn */
begin
for each v V[G] do /* khởi tạo */
begin
d[v] := ; p[v] := NIL
end;
d[s] := 0;
for i:= 1 to |V|-1 do /* thực hiện |V|-1 chuyến
for each edge (u,v ) E do
if d[v] > d[u] + w(u, v) then
begin
d[v] := d[u] + w(u, v); p[v] := u
end
/* kiểm tra có tồn tại chu trình với tổng trọng số âm
for each edge (u,v ) E do
if d[v] > d[u] + w(u, v) then return FALSE
return TRUE
end
27
Giải thích giải thuật Bellman-Ford
Sau khi thực hiện việc khởi tạo hai mảng d và p, giải thuật
thực hiện |V|-1 chuyến duyệt qua tất cả các cạnh trong đồ thị.
Một lần duyệt qua các đỉnh trong đồ thị, hai mảng d và p sẽ
được điều chỉnh giá trị.
Sau khi hoàn tất |V|-1 chuyến duyệt qua tất cả các cạnh, giải
thuật kiểm tra xem có tồn tại chu trình với tổng trọng số âm
hay không bằng vòng lặp cuối cùng trong giải thuật và trả về
giá trị bool phù hợp.
Giải thuật Bellman-Ford có độ phức tạp O(VE) vì lý do sau
đây. Với vòng lặp khởi tạo có độ phức tạp O(V) và |V|-1
chuyến duyệt qua tất cả các cạnh có độ phức tạp (|V|-1).E
tức là O(VE). Tóm lại: O(V) + O(VE) O(VE).
28
Thí dụ Hình 3.14a
Cho đồ thị có hướng có trọng số ở Hình 3.14. Sau khi khởi tạo, các
mảng d và p có giá trị như sau:
s t x y z
d 0
p nil nil nil nil
Trạng thái của đồ thị sau bước khởi tạo được mô tả ở Hình 3.14a.
Trong 4 lượt lặp tiếp theo, thứ tự để xét các cạnh trong đồ thị:
(s, t), (s, y), (t, x), (t, y), (t,z), (y,x), (y, z), (x,t), (z, x), (z, s),
29
Chuyến 1
Xét (s,t): s t x y z
Thứ tự để xét các cạnh :
d 0 6 (s, t), (s, y), (t, x), (t, y), (t,z),
p s nil nil nil (y,x), (y, z), (x,t), (z, x), (z, s)
Xét (s,y): s t x y z
d 0 6 7
p s nil s nil
Hình 3.14b
30
Chuyến 2
Xét (t,x): s t x y z
Thứ tự để xét các cạnh :
d 0 6 11 7 (s, t), (s, y), (t, x), (t, y), (t,z),
p s t s nil (y,x), (y, z), (x,t), (z, x), (z, s)
Xét (t,z): s t x y z
d 0 6 11 7 2
p s t s t
Xét (y,x): s t x y z
d 0 6 4 7 2
p s y s t
Hình 3.14c
31
Chuyến 3
Thứ tự để xét các cạnh :
(s, t), (s, y), (t, x), (t, y), (t,z),
Xét (x, t): s t x y z (y,x), (y, z), (x,t), (z, x), (z, s)
d 0 2 4 7 2
p x y s t
Hình 3.14d
32
Chuyến 4
Xét (t, z): s t x y z
d 0 2 4 7 -2 Sau chuyến 4, tình trạng
p x y s t của đồ thị như trong Hình
3.14e. Đến đây, giải thuật
kết thúc.
Tóm lại:
lối đi ngắn nhất từ s đến t = 2
(s - y – x - t);
từ s đến x = 4 (s - y - x) ;
từ s đến y = 7 (s – y);
từ s đến z = -2 (s - y – x - t – z);
33
Kết luận
Giải thuật Warshall và giải thuật Floyd thể hiện một chiến
lược thiết kế giải thuật đặc biệt: các kết quả trung gian
được tính và lưu vào một bảng và sự tính toán bảng tại
một lượt lặp dựa trên trạng thái của bảng tại lượt lặp
trước. Quy hoạch động.
Giải thuật Dijkstra thể hiện tinh thần của giải thuật tham
lam và có sử dụng hàng đợi có thứ tự ưu tiên như là một
cấu trúc dữ liệu hỗ trợ.
Giải thuật Bellman-Ford thể hiện tinh thần của giải thuật
quy hoạch động.
34