V. MỘT SỐ BĂI TOÂN TRÍN ĐỒ THỊ
3. Băi toân tìm bao đóng chuyển tiếp (transitive closure)
Trong một số trường hợp ta chỉ cần xâc định có hay không có đường đi nối giữa hai đỉnh i,j bất kỳ. Giải thuật Floyd có thể đặc biệt hoâ để giải băi toân năy. Bđy giờ khoảng câch giữa
i,j lă không quan trọng mă ta chỉ cần biết i,j có nối nhau không do đó ta cho C[i,j]=1 (~true) nếu i,j được nối nhau bởi một cạnh, ngược lại C[i,j]=0 (~false). Lúc năy mảng A[i,j] không cho khoảng câch ngắn nhất giữa i,j mă nó cho biết lă có đường đi từ i đến j hay không. A gọi lă bao đóng chuyển tiếp của đồ thị G có biểu diễn ma trận kề lă C. Giải thuật Floyd sửa đổi như trín gọi lă giải thuật Warshall.
int A[n,n], C[n,n];
void Warshall() {
int i,j,k;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
A[i-1,j-1] = C[i-1,j-1]; for (k=1; k<=n; k++)
for (i=1; i<=n; i++)
for (j=1; j<=n; j++) if (A[i-1,j-1] == 0) then
A[i-1,j-1] =A[i-1,k-1] && A[k-1,j-1]; }
4. Băi toân tìm cđy bao trùm tối thiểu (minimum-cost spanning tree)
Giả sử ta có một đồ thị vô hướng G=(V,E). Đồ thị G gọi lă liín thông nếu tồn tại đường đi giữa hai đỉnh bất kỳ. Băi toân tìm cđy bao trùm tối thiểu (hoặc cđy phủ tối thiểu) lă tìm một tập hợp T chứa câc cạnh của một đồ thị liín thông G sao cho V cùng với tập câc cạnh năy cũng lă một đồ thị liín thông, tức lă (V,T) lă một đồ thị liín thông. Hơn nữa tổng độ dăi câc cạnh trong T lă nhỏ nhất. Một thể hiện của băi toân năy trong thực tế lă băi toân thiết lập mạng truyền thông, ở đó câc đỉnh lă câc thănh phố còn câc cạnh của cđy bao trùm lă đường nối mạng giữa câc thănh phố.
Giả sử G có n đỉnh được đânh số 1..n. Giải thuật Prim để giải băi toân năy như sau: Bắt đầu, tập ta khởi tạo tập U bằng 1 đỉnh năo đó, đỉnh 1 chẳng hạn, U = {1}, T=U
Sau đó ta lặp lại cho đến khi U=V, tại mỗi bước lặp ta chọn cạnh nhỏ nhất (u,v) sao cho u ∈ U vă v ∈ V-U. Thím v văo U vă (u,v) văo T. Khi giải thuật kết thúc thì (U,T) lă một cđy phủ tối tiểu.
Ví dụ, âp dụng giải thuật Prim để tìm cđy bao trùm tối thiểu của đồ thị liín thông hình V.6.
¾ Bước khởi đầu: U={1}, T=∅.
¾ Bước kế tiếp ta có cạnh (1,3)=1 lă cạnh ngắn nhất thoả mên điều kiện trong giải thuật Prim nín: U={1,3}, T={(1,3)}.
¾ Kế tiếp thì cạnh (3,6)=4 lă cạnh ngắn nhất thoả mên điều kiện trong giải thuật Prim nín: U={1,3,6}, T={(1,3),(3,6)}.
¾ Kế tiếp thì cạnh (6,4)=2 lă cạnh ngắn nhất thoả mên điều kiện trong giải thuật Prim nín: U={1,3,6,4}, T={(1,3),(3,6),(6,4)}.
¾ Tiếp tục, cạnh (3,2)=5 lă cạnh ngắn nhất thoả mên điều kiện trong giải thuật Prim nín: U={1,3,6,4,2}, T={(1,3),(3,6),(6,4),(3,2)}.
¾ Cuối cùng, cạnh (2,5)=3 lă cạnh ngắn nhất thoả mên điều kiện trong giải thuật Prim nín: U={1,3,6,4,2,5}, T={(1,3),(3,6),(6,4),(3,2),(2,5)}. Giải thuật dừng vă ta có cđy bao trùm như trong hình V.7.
Giải thuật Prim được viết lại như sau:
void Prim(graph G, set_of_edges *T) {
set_of_vertices U; //tập hợp câc đỉnh vertex u,v; //u,v lă câc đỉnh
T = ∅; U = [1];
while (U≠V) do // V lă tập hợp câc đỉnh của G {
gọi (u,v) lă cạnh ngắn nhất sao cho u ∈ U vă v ∈ V-U; U = U ∪ [v];
T = T ∪ [(u,v)]; }
}
Băi toân cđy bao trùm tối thiểu còn có thểđược giải bằng giải thuật Kruskal như sau:
Khởi đầu ta cũng cho T= ∅ giống như trín, ta thiết lập đồ thị khởi đầu G'=(V,T).
Xĩt câc cạnh của G theo thứ tự độ dăi tăng dần. Với mỗi cạnh được xĩt ta sẽ đưa nó văo T nếu nó không lăm cho G' có chu trình.
Ví dụ âp dụng giải thuật Kruskal để tìm cđy bao trùm cho đồ thị hình V.6. Câc cạnh của đồ thị được xếp theo thứ tự tăng dần lă.
(1,3)=1, (4,6)=2, (2,5)=3, (3,6)=4, (1,4)=(2,3)=(3,4)=5, (1,2)=(3,5)= (5,6)=6. Ò Bước khởi đầu T= ∅
Ò Lần lặp 1: T={(1,3)} Ò Lần lặp 2: T={(1,3),(4,6)} Ò Lần lặp 3: T={(1,3),(4,6),(2,5)} Ò Lần lặp 4: T={(1,3),(4,6),(2,5),(3,6)} Ò Lần lặp 5:
Cạnh (1,4) không được đưa văo T vì nó sẽ tạo ra chu trình 1,3,6,4,1. Kế tiếp cạnh (2,3) được xĩt vă được đưa văo T.
T={(1,3),(4,6),(2,5),(3,6),(2,3)}
Không còn cạnh năo có thể được đưa thím văo T mă không tạo ra chu trình. Vậy ta có cđy bao trùm tối thiểu cũng giống như trong hình V.7.
BĂI TẬP
1. Viết biểu diễn đồ thị V.8 bằng: - Ma trận kề.
- Danh sâch câc đỉnh kề.
2. Duyệt đồ thị hình V.8 (xĩt câc đỉnh theo thứ tự a,b,c...) - Theo chiều rộng bắt đầu từ a.
- Theo chiều sđu bắt đầu từ f
3. Âp dụng giải thuật Dijkstra cho đồ thị hình V.8, với đỉnh nguồn lă
a.
4. Viết biểu diễn đồ thị V.9 bằng: Ma trận kề.
Danh sâch câc đỉnh kề.
5. Duyệt đồ thị hình V.9 (xĩt câc đỉnh theo thứ tự A,B,C...) Theo chiều rộng bắt đầu từ A.
Theo chiều sđu bắt đầu từ B.
6. Âp dụng giải thuật Dijkstra cho đồ thị hình V.9, với đỉnh nguồn lă A. 7. Tìm cđy bao trùm tối thiểu của đồ thị hình V.9 bằng
Giải thuật Prim. Giải thuật Kruskal.
8. Căi đặt đồ thị có hướng bằng ma trận kề rồi viết câc giải thuật: Duyệt theo chiều rộng.
Duyệt theo chiều sđu.
Tìm đường đi ngắn nhất từ một đỉnh cho trước (Dijkstra). Tìm đường đi ngắn nhất giữa tất cả câc cặp đỉnh (Floyd).
9. Căi đặt đồ thị có hướng bằng danh sâch câc đỉnh kề rồi viết câc giải thuật: Duyệt theo chiều rộng.
Duyệt theo chiều sđu.
10. Căi đặt đồ thị vô hướng bằng ma trận kề rồi viết câc giải thuật: Duyệt theo chiều rộng.
Duyệt theo chiều sđu.
Tìm đường đi ngắn nhất từ một đỉnh cho trước (Dijkstra). Tìm đường đi ngắn nhất giữa tất cả câc cặp đỉnh (Floyd).
Tìm cđy bao trùm tối thiểu (Prim, Kruskal).
Căi đặt thuật toân Greedy cho băi toân tô mău đồ thị (Gợi ý: xem giải thuật trong chương 1)
11. Căi đặt đồ thị vô hướng bằng danh sâch câc đỉnh kề rồi viết câc giải thuật: Duyệt theo chiều rộng.
Duyệt theo chiều sđu.
12. Hêy viết một chương trình, trong đó, căi đặt đồ thị vô hướng bằng cấu trúc ma trận kề rồi viết câc thủ tục/hăm sau:
Nhập toạ độ n đỉnh của đồ thị.
Giả sử đồ thị lă đầy đủ, tức lă hai đỉnh bất kỳ đều có cạnh nối, vă giả sử giâ của mỗi cạnh lă độ dăi của đoạn thẳng nối hai cạnh. Hêy tìm:
Đường đi ngắn nhất từ một đỉnh cho trước (Dijkstra). Đường đi ngắn nhất giữa tất cả câc cặp đỉnh (Floyd). Cđy bao trùm tối thiểu (Prim, Kruskal).
Thể hiện đồ thị lín măn hình đồ hoạ, câc cạnh thuộc cđy bao trùm tối thiểu được vẽ bằng một mău khâc với câc cạnh khâc.