Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 36 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
36
Dung lượng
2,22 MB
Nội dung
Các thuật toán đồ thị 203 Init; Solve; Close(fo); end Bài tập Bài Phương pháp cài đặt nói hay hiệu quả, địi hỏi ta phải hiểu rõ chất thuật tốn, khơng dễ nhầm Trên thực tế, cịn có phương pháp khác dễ hiểu hơn, tính hiệu có chút Hãy viết chương trình mơ tả phương pháp sau: Vẫn dùng thuật tốn tìm kiếm theo chiều sâu với thủ tục Visit nói đầu mục, đánh số lại đỉnh từ tới n theo thứ tự duyệt xong, sau đảo chiều tất cung đồ thị Xét đỉnh theo thứ tự từ đỉnh duyệt xong sau tới đỉnh duyệt xong đầu tiên, với đỉnh đó, ta lại dùng thuật tốn tìm kiếm đồ thị (BFS hay DFS) liệt kê đỉnh đến từ đỉnh xét, thành phần liên thông mạnh Lưu ý liệt kê xong thành phần nào, ta loại đỉnh thành phần khỏi đồ thị Tính đắn phương pháp hình dung khơng khó khăn: Trước hết ta thêm vào đồ thị đỉnh x cung (x, v) với v, sau gọi Visit(x) để xây dựng DFS gốc x Hiển nhiên x chốt thành phần liên thông gồm x Sau bỏ đỉnh x khỏi DFS, phân rã thành Đỉnh r duyệt xong sau chắn gốc (bởi duyệt xong chắn lùi x) suy r chốt Hơn nữa, đỉnh u tới r u phải thuộc gốc r Bởi giả sử phản chứng u thuộc khác u phải thăm trước r (do gốc r thăm tới sau cùng), có nghĩa Visit(u) r chưa thăm Vậy nên r thuộc nhánh DFS gốc u, mâu thuẫn với lập luận r gốc Từ suy u tới r r tới u, tức đảo chiều cung, r tới đỉnh đỉnh thuộc thành phần liên thơng chốt r Loại bỏ thành phần liên thông với chốt r khỏi đồ thị Cây gốc r lại phân rã thành nhiều Lập luận tương tự với v' đỉnh duyệt xong sau (Hình 66) Ví dụ: Lê Minh Hồng 204 Chun đề 11 10 5 11 8 10 Hình 66: Đánh số lại, đảo chiều cung duyệt BFS với cách chọn đỉnh xuất phát ngược lại với thứ tự duyệt xong (thứ tự 11, 10… 3, 2, 1) Bài Thuật tốn Warshall áp dụng tìm bao đóng đồ thị có hướng, kiểm tra tính liên thơng mạnh đồ thị có hướng hai cách: Dùng thuật tốn tìm kiếm đồ thị thuật tốn Warshall, sau so sánh ưu, nhược điểm phương pháp Bài Trên mặt phẳng với hệ toạ độ Decattes vng góc cho n đường trịn, đường tròn xác định số thực (X, Y, R) (X, Y) toạ độ tâm R bán kính Hai đường trịn gọi thơng chúng có điểm chung Hãy chia đường trịn thành số tối thiểu nhóm cho hai đường trịn nhóm sang sau số hữu hạn bước di chuyển hai đường trịn thơng Đại học Sư phạm Hà Nội, 1999-2002 Các thuật tốn đồ thị 205 §5 VÀI ỨNG DỤNG CỦA CÁC THUẬT TỐN TÌM KIẾM TRÊN ĐỒ THỊ 5.1 XÂY DỰNG CÂY KHUNG CỦA ĐỒ THỊ Cây đồ thị vơ hướng, liên thơng, khơng có chu trình đơn Đồ thị vơ hướng khơng có chu trình đơn gọi rừng (hợp nhiều cây) Như thành phần liên thông rừng Khái niệm sử dụng rộng rãi nhiều lĩnh vực khác nhau: Nghiên cứu cấu trúc phân tử hữu cơ, xây dựng thuật toán tổ chức thư mục, thuật tốn tìm kiếm, lưu trữ nén liệu… 5.1.1 Định lý (Daisy Chain Theorem) Giả sử T = (V, E) đồ thị vô hướng với n đỉnh Khi mệnh đề sau tương đương: T T khơng chứa chu trình đơn có n - cạnh T liên thông cạnh cầu Giữa hai đỉnh T tồn đường đơn T khơng chứa chu trình đơn thêm vào cạnh ta thu chu trình đơn T liên thơng có n - cạnh Chứng minh: 1⇒2: "T cây" ⇒ "T không chứa chu trình đơn có n - cạnh" Từ T cây, theo định nghĩa T khơng chứa chu trình đơn Ta chứng minh T có n đỉnh phải có n - cạnh quy nạp theo số đỉnh n Rõ ràng n = có đỉnh chứa cạnh Nếu n > đồ thị hữu hạn nên số đường đơn T hữu hạn, gọi P = (v1, v2, …, vk) đường dài (qua nhiều cạnh nhất) T Đỉnh v1 khơng thể có cạnh nối với đỉnh số đỉnh v3, v4, …, vk Bởi có cạnh (v1, vp) (3 ≤ p ≤ k) ta thiết lập chu trình đơn (v1, v2, …, vp, v1) Mặt khác, đỉnh v1 khơng thể có cạnh nối với đỉnh khác đỉnh P có cạnh (v1, v0) (v0∉P) ta thiết lập đường (v0, v1, v2, …, vk) dài đường P Vậy đỉnh v1 có cạnh nối với v2 hay v1 đỉnh treo Loại bỏ v1 cạnh (v1, v2) khỏi T ta đồ thị có n - đỉnh, theo giả thiết quy nạp có n - cạnh Vậy T có n - cạnh 2⇒3: "T khơng chứa chu trình đơn có n - cạnh"⇒"T liên thơng cạnh cầu" Giả sử T có k thành phần liên thơng T1, T2, …, Tk Vì T khơng chứa chu trình đơn nên thành phần liên thông T không chứa chu trình đơn, tức T1, T2, …, Tk Gọi n1, n2, …, nk số đỉnh T1, T2, …, Tk T1 có n1 - cạnh, T2 có n2 - cạnh…, Lê Minh Hoàng 206 Chuyên đề Tk có nk - cạnh Cộng lại ta có số cạnh T n1 + n2 + … + nk - k = n - k cạnh Theo giả thiết, T có n - cạnh, suy k = 1, đồ thị có thành phần liên thông đồ thị liên thông Bây T liên thông, bỏ cạnh T T cịn n - cạnh không liên thông T liên thông T khơng có chu trình nên T có n - cạnh Điều chứng tỏ cạnh T cầu 3⇒4: "T liên thơng cạnh cầu"⇒"Giữa hai đỉnh T có đường đơn" Gọi x y đỉnh T, T liên thơng nên có đường đơn từ x tới y Nếu tồn đường đơn khác từ x tới y ta bỏ cạnh (u, v) nằm đường thứ không nằm đường thứ hai từ u đến v cách: từ u theo chiều tới x theo cạnh thuộc đường thứ nhất, sau từ x tới y theo đường thứ hai, lại từ y tới v theo cạnh thuộc đường thứ Điều mâu thuẫn với giả thiết (u, v) cầu 4⇒5: "Giữa hai đỉnh T có đường đơn"⇒"T khơng chứa chu trình đơn thêm vào cạnh ta thu chu trình đơn" Thứ T khơng chứa chu trình đơn T chứa chu trình đơn chu trình qua hai đỉnh u, v Rõ ràng dọc theo cạnh chu trình từ u có hai đường đơn tới v Vô lý Giữa hai đỉnh u, v T có đường đơn nối u với v, thêm cạnh (u, v) vào đường tạo thành chu trình 5⇒6: "T khơng chứa chu trình đơn thêm vào cạnh ta thu chu trình đơn"⇒"T liên thơng có n - cạnh" Gọi u v hai đỉnh T, thêm vào T cạnh (u, v) theo giả thiết tạo thành chu trình chứa cạnh (u, v) Loại bỏ cạnh phần cịn lại chu trình đường từ u tới v Mọi cặp đỉnh T có đường nối chúng tức T liên thơng, theo giả thiết T khơng chứa chu trình đơn nên T có n - cạnh 6⇒1: "T liên thơng có n - cạnh"⇒"T cây" Giả sử T khơng T có chu trình, huỷ bỏ cạnh chu trình T liên thơng, đồ thị nhận có chu trình lại huỷ cạnh chu trình Cứ ta nhận đồ thị liên thông khơng có chu trình Đồ thị lại có < n - cạnh (vơ lý) Vậy T 5.1.2 Định nghĩa Giả sử G = (V, E) đồ thị vô hướng Cây T = (V, F) với F⊂E gọi khung đồ thị G Tức loại bỏ số cạnh G để gọi khung (hay bao trùm đồ thị) Dễ thấy với đồ thị vô hướng liên thơng có nhiều khung (Hình 67) Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 207 T2 T1 G T3 Hình 67: Đồ thị G số ví dụ khung T1, T2, T3 Điều kiện cần đủ để đồ thị vơ hướng có khung đồ thị phải liên thơng Số khung đồ thị đầy đủ Kn nn-2 5.1.3 Thuật toán xây dựng khung Xét đồ thị vô hướng liên thơng G = (V, E) có n đỉnh, có nhiều thuật toán xây dựng khung G a) Xây dựng khung thuật toán hợp Trước hết, đặt T = (V, ∅); T không chứa cạnh coi T gồm n rời rạc, có đỉnh Sau xét cạnh G, cạnh xét nối hai khác T thêm cạnh vào T, đồng thời hợp hai lại thành Cứ làm kết nạp đủ n - cạnh vào T ta T khung đồ thị Các phương pháp kiểm tra cạnh có nối hai khác hay không kỹ thuật hợp hai bàn kỹ thuật toán Kruskal §9 b) Xây dựng khung thuật tốn tìm kiếm đồ thị Áp dụng thuật tốn BFS hay DFS đỉnh S, bước từ đỉnh u tới thăm đỉnh v, ta thêm vào thao tác ghi nhận cạnh (u, v) vào khung Do đồ thị liên thơng nên thuật tốn xuất phát từ S tới thăm tất đỉnh lại, đỉnh lần, tức trình duyệt ghi nhận n - cạnh Tất cạnh khơng tạo thành chu trình đơn thuật tốn khơng thăm lại đỉnh thăm Theo mệnh đề tương đương thứ hai, ta có cạnh ghi nhận tạo thành khung đồ thị 1 10 11 a) 10 11 b) Hình 68: Cây khung DFS (a) khung BFS (b) (Mũi tên chiều thăm đỉnh) Lê Minh Hồng 208 Chun đề 5.2 TẬP CÁC CHU TRÌNH CƠ BẢN CỦA ĐỒ THỊ Xét đồ thị vô hướng liên thông G = (V, E); gọi T = (V, F) khung Các cạnh khung gọi cạnh trong, cạnh khác cạnh Nếu thêm cạnh ngồi e∈E \ F vào khung T, ta chu trình đơn T, ký hiệu chu trình Ce Tập chu trình: Ω = {Ce⏐ e∈E \ F} gọi tập chu trình sở đồ thị G Các tính chất quan trọng tập chu trình sở: Tập chu trình sở phụ thuộc vào khung, hai khung khác cho hai tập chu trình sở khác Nếu đồ thị liên thơng có n đỉnh m cạnh, khung có n - cạnh, cịn lại m - n + cạnh Tương ứng với cạnh ngồi có chu trình sở, số chu trình sở đồ thị liên thông m - n + 1 Tập chu trình sở tập nhiều chu trình thoả mãn: Mỗi chu trình có cạnh riêng, cạnh khơng nằm chu trình khác Bởi có tập gồm t chu trình thoả mãn điều việc loại bỏ cạnh riêng chu trình khơng làm tính liên thơng đồ thị, đồng thời khơng ảnh hưởng tới tồn chu trình khác Như loại bỏ tất cạnh riêng đồ thị liên thơng cịn m - t cạnh Đồ thị liên thơng khơng thể có n - cạnh nên ta có m - t ≥ n - hay t ≤ m - n + Mọi cạnh chu trình đơn phải thuộc chu trình sở Bởi có cạnh (u, v) khơng thuộc chu trình sở nào, ta bỏ cạnh đồ thị liên thơng khơng ảnh hưởng tới tồn chu trình sở Lại bỏ tiếp cạnh chu trình sở đồ thị liên thơng lại m - (m - n + 1) - = n - cạnh Điều vô lý Đối với đồ thị G = (V, E) có n đỉnh m cạnh, có k thành phần liên thơng, ta xét thành phần liên thơng xét rừng khung thành phần Khi mở rộng khái niệm tập chu trình sở cho đồ thị vơ hướng tổng quát: Mỗi thêm cạnh không nằm khung vào rừng, ta chu trình đơn, tập chu trình đơn tạo thành cách ghép cạnh gọi tập chu trình sở đồ thị G Số chu trình sở m - n + k 5.3 ĐỊNH CHIỀU ĐỒ THỊ VÀ BÀI TOÁN LIỆT KÊ CẦU Bài toán đặt cho đồ thị vô hướng liên thông G = (V, E), thay cạnh đồ thị cung định hướng để đồ thị có hướng liên thơng mạnh Nếu có phương án định chiều G gọi đồ thị định chiều Bài tốn định chiều đồ thị có ứng dụng rõ sơ đồ giao thông đường Chẳng hạn trả lời câu hỏi: Trong hệ thống đường phố, Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 209 liệu quy định đường phố thành đường chiều mà đảm bảo lại hai nút giao thông hay không 5.3.1 Phép định chiều DFS Xét mô hình duyệt đồ thị thuật tốn tìm kiếm theo chiều sâu đỉnh Vì đồ thị vơ hướng liên thơng nên q trình tìm kiếm thăm hết đỉnh procedure Visit(u ∈ V); begin ; for (∀v: (u, v) ∈ E) if then Visit(v); end; begin ; Visit(1); end; Coi cạnh đồ thị tương đương với hai cung có hướng ngược chiều Thuật tốn tìm kiếm theo chiều sâu theo mơ hình duyệt qua hết đỉnh đồ thị tất cung Quá trình duyệt cho ta tìm kiếm DFS Ta có nhận xét sau: Nhận xét 1: Quá trình duyệt khơng có cung chéo (cung từ nhánh DFS thăm sau tới nhánh DFS thăm trước) Thật vậy, trình duyệt xét tới cung (u, v): Nếu u thăm trước v có nghĩa Visit(u) gọi v chưa thăm, thủ tục Visit(u) xây dựng nhánh DFS gốc u gồm đỉnh chưa thăm đến từ u, suy v nằm nhánh DFS gốc u ⇒ v hậu duệ u, hay (u, v) cung DFS cung xuôi Nếu u thăm sau v (v thăm trước u), tương tự trên, ta suy u nằm nhánh DFS gốc v, v tiền bối u ⇒ (u, v) cung ngược Nhận xét 2: Trong trình duyệt đồ thị theo chiều sâu, duyệt qua cung (u, v) ta bỏ cung (v, u) (Tức duyệt qua cung (u, v) ta định chiều cạnh (u, v) theo chiều từ u tới v), ta phép định chiều đồ thị gọi phép định chiều DFS Lê Minh Hoàng 210 Chuyên đề 1 2 8 9 10 10 Hình 69: Phép định chiều DFS Nhận xét 3: Với phép định chiều trên, cung DFS cung ngược, khơng cịn lại cung xi Bởi đồ thị vơ hướng ban đầu, ta coi cạnh hai cung có hướng ngược chiều với cung xi ta có cung ngược chiều với cung ngược Do tính chất DFS, cung ngược duyệt trước cung xuôi tương ứng, nên định chiều cạnh theo cung ngược cung xi bị huỷ khơng bị xét tới Nhận xét 4: Trong đồ thị vô hướng ban đầu, cạnh bị định hướng thành cung ngược cạnh ngồi khung DFS Chính vậy, chu trình sở đồ thị vơ hướng ban đầu chu trình đồ thị có hướng tạo (Đây phương pháp hiệu để liệt kê chu trình sở khung DFS: Vừa duyệt DFS vừa định chiều, duyệt phải cung ngược (u, v) truy vết đường DFS để tìm đường từ v đến u, sau nối thêm cung ngược (u, v) để chu trình sở) Định lý: Điều kiện cần đủ để đồ thị vô hướng liên thơng định chiều cạnh đồ thị nằm chu trình đơn (Hay nói cách khác cạnh đồ thị cầu) Chứng minh: Gọi G = (V, E) đồ thị vô hướng liên thông "⇒" Nếu G định chiều sau định hướng đồ thị liên thông mạnh G' Với cạnh định chiều thành cung (u, v) tồn đường đơn G' theo cạnh định hướng từ v u Đường nối thêm cung (u, v) thành chu trình đơn có hướng G' Tức đồ thị ban đầu, cạnh (u, v) nằm chu trình đơn "⇐" Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 211 Nếu cạnh G nằm chu trình đơn, ta chứng minh rằng: phép định chiều DFS tạo đồ thị G' liên thông mạnh Trước hết ta chứng minh (u, v) cạnh G có đường từ u tới v G' Thật vậy, (u, v) nằm chu trình đơn, mà cạnh chu trình đơn phải thuộc chu trình sở đó, nên có chu trình sở chứa u v Chu trình sở qua phép định chiều DFS chu trình G' nên theo cạnh định hướng chu trình đó, ta từ u tới v ngược lại Nếu u v đỉnh G G liên thơng, tồn đường (u=x0, x1, …, xn=v) Vì (xi, xi + 1) cạnh G nên G', từ xi đến xi+1 Suy từ u đến v cạnh định hướng G' 5.3.2 Cài đặt Với kết chứng minh trên, ta suy được: Nếu đồ thị liên thơng cạnh nằm chu trình đơn phép định chiều DFS cho đồ thị liên thông mạnh Cịn khơng, phép định chiều DFS cho đồ thị định hướng có thành phần liên thông mạnh nhất, cạnh không nằm chu trình đơn (cầu) đồ thị ban đầu định hướng thành cung nối hai thành phần liên thơng mạnh Ta cài đặt thuật tốn với đồ thị vô hướng: liệt kê cầu định chiều cạnh để đồ thị có thành phần liên thơng mạnh nhất: Đánh số đỉnh theo thứ tự thăm DFS, gọi Numbering[u] số thứ tự đỉnh u theo cách đánh số Trong q trình tìm kiếm DFS, duyệt qua cạnh định chiều ln cạnh Định nghĩa thêm Low[u] giá trị Numbering nhỏ đỉnh đến từ nhánh DFS gốc u cung ngược Tức nhánh DFS gốc u có nhiều cung ngược hướng lên phía gốc ta ghi nhận lại cung ngược hướng lên cao Nếu nhánh DFS gốc u khơng chứa cung ngược ta cho Low[u] = +∞ Cụ thể cách cực tiểu hoá Low[u] sau: Trong thủ tục Visit(u), trước hết ta đánh số thứ tự thăm cho đỉnh u (Numbering[u]) khởi gán Low[u] = +∞ Sau đó, xét tất đỉnh v kề u, định chiều cạnh (u, v) thành cung (u, v) Có hai khả xảy ra: v chưa thăm ta gọi Visit(v) để thăm v cực tiểu hố Low[u] theo cơng thức: Low[u] := min(Low[u]cũ, Low[v]) v thăm ta cực tiểu hố Low[u] theo công thức: Low[u] := min(Low[u]cũ, Numbering[v]) Lê Minh Hồng 212 Chun đề Dễ thấy cách tính đắn v chưa thăm nhánh DFS gốc v nằm nhánh DFS gốc u cung ngược nhánh DFS gốc v cung ngược nhánh DFS gốc u Còn v thăm (u, v) cung ngược 1 3 2 5 9 11 10 11 10 4 Đồ thị vô hướng Đồ thị định chiều Giá trị Numbering[.] ghi vòng tròn Giá trị Low[.] ghi bên cạnh Hình 70: Phép đánh số ghi nhận cung ngược lên cao Nếu từ đỉnh u tới thăm đỉnh v, (u, v) cung DFS Khi đỉnh v duyệt xong, lùi thủ tục Visit(u), ta so sánh Low[v] Numbering[u] Nếu Low[v] > Numbering[u] tức nhánh DFS gốc v khơng có cung ngược lên phía v Tức cạnh (u, v) khơng thuộc chu trình sở cả, tức cạnh cầu {Đồ thị G = (V, E)} procedure Visit(u∈V); begin ; for (∀v: (u, v)∈E) begin ; if then begin Visit(v); if Low[v] > Numbering[u] then ; Low[u] := Min(Low[u], Low[v]); {Cực tiểu hoá Low[u] theo Low[v]} end else {v thăm} Low[u] := Min(Low[u], Numbering[v]); {Cực tiểu hoá Low[u] theo Numbering[v]} end; end; begin for (∀u∈V) if then Visit(u); ; end Input: file văn GRAPH.INP • Dịng ghi số đỉnh n (n ≤ 100) số cạnh m đồ thị cách dấu cách Đại học Sư phạm Hà Nội, 1999-2002 224 Chuyên đề Break; end; if u = Get then {Nếu phần tử đỉnh ngăn xếp u ⇒ vịng lặp khơng tìm thấy đỉnh kề với u} begin Inc(count); Write(f, Pop, ' '); {In phần tử đỉnh ngăn xếp} end; end; Close(f); end; begin Enter; FindEulerCircuit; end Bài tập Trên mặt phẳng cho n hình chữ nhật có cạnh song song với trục toạ độ Hãy chu trình: Chỉ cạnh hình chữ nhật Trên cạnh hình chữ nhật, ngoại trừ giao điểm với cạnh hình chữ nhật khác qua nhiều lần, điểm cịn lại qua lần C B E M J F K A D H I N G L M D A B C M F G N L I J K N H E M Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 225 §7 CHU TRÌNH HAMILTON, ĐƯỜNG ĐI HAMILTON, ĐỒ THỊ HAMILTON 7.1 ĐỊNH NGHĨA Cho đồ thị G = (V, E) có n đỉnh Chu trình (x1, x2, …, xn, x1) gọi chu trình Hamilton xi ≠ xj với ≤ i < j ≤ n Đường (x1, x2, …, xn) gọi đường Hamilton xi ≠ xj với ≤ i < j ≤ n Có thể phát biểu cách hình thức: Chu trình Hamilton chu trình xuất phát từ đỉnh, thăm tất đỉnh lại đỉnh lần, cuối quay trở lại đỉnh xuất phát Đường Hamilton đường qua tất đỉnh đồ thị, đỉnh lần Khác với khái niệm chu trình Euler đường Euler, chu trình Hamilton khơng phải đường Hamilton có đỉnh xuất phát thăm tới lần Ví dụ: Xét đơn đồ thị G1, G2, G3 Hình 75: b c a b a b e e d d c d c f a G1 G2 g G3 Hình 75 Đồ thị G1 có chu trình Hamilton (a, b, c, d, e, a) G2 khơng có chu trình Hamilton deg(a) = có đường Hamilton (a, b, c, d) G3 khơng có chu trình Hamilton lẫn đường Hamilton 7.2 ĐỊNH LÝ Đồ thị vô hướng G, tồn k đỉnh cho xố k đỉnh với cạnh liên thuộc chúng đồ thị nhận có nhiều k thành phần liên thơng Thì khẳng định G khơng có chu trình Hamilton Mệnh đề phản đảo định lý cho ta điều kiện cần để đồ thị có chu trình Hamilton Định lý Dirac (1952): Đồ thị vơ hướng G có n đỉnh (n ≥ 3) Khi đỉnh v G có deg(v) ≥ n/2 G có chu trình Hamilton Đây điều kiện đủ để đồ thị có chu trình Hamilton Đồ thị có hướng G liên thơng mạnh có n đỉnh Nếu deg+(v) ≥ n / deg-(v) ≥ n / với đỉnh v G có chu trình Hamilton Lê Minh Hoàng 226 Chuyên đề 7.3 CÀI ĐẶT Dưới ta cài đặt chương trình liệt kê tất chu trình Hamilton xuất phát từ đỉnh 1, chu trình Hamilton khác có cách hốn vị vịng quanh Lưu ý nay, người ta chưa tìm phương pháp thực hiệu phương pháp quay lui để tìm dù chu trình Hamilton đường Hamilton trường hợp đồ thị tổng quát Input: file văn HAMILTON.INP • Dịng ghi số đỉnh n (2 ≤ n ≤ 100) số cạnh m đồ thị cách dấu cách • m dịng tiếp theo, dịng có dạng hai số nguyên dương u, v cách dấu cách, thể u, v hai đỉnh kề đồ thị Output: file văn HAMILTON.OUT liệt kê chu trình Hamilton HAMILTON.INP 56 12 13 24 35 41 52 HAMILTON.OUT 135241 142531 P_4_07_1.PAS * Thuật tốn quay lui liệt kê chu trình Hamilton program All_of_Hamilton_Circuits; const InputFile = 'HAMILTON.INP'; OutputFile = 'HAMILTON.OUT'; max = 100; var fo: Text; a: array[1 max, max] of Boolean; {Ma trận kề đồ thị: a[u, v] = True ⇔ (u, v) cạnh} Free: array[1 max] of Boolean; {Mảng đánh dấu Free[v] = True chưa qua đỉnh v} X: array[1 max] of Integer; {Chu trình Hamilton tìm là; 1=X[1]→X[2] → … →X[n] →X[1]=1} n: Integer; procedure Enter; var i, u, v, m: Integer; f: Text; begin Assign(f, InputFile); Reset(f); FillChar(a, SizeOf(a), False); ReadLn(f, n, m); for i := to m begin ReadLn(f, u, v); a[u, v] := True; a[v, u] := True; end; Close(f); end; procedure PrintResult; {In kết tìm thấy chu trình Hamilton} var i: Integer; begin for i := to n Write(fo, X[i], ' '); WriteLn(fo, X[1]); Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 227 end; procedure Try(i: Integer); {Thử cách chọn đỉnh thứ i hành trình} var j: Integer; begin for j := to n {Đỉnh thứ i (X[i]) chọn đỉnh} if Free[j] and a[x[i - 1], j] then {kề với X[i - 1] chưa bị qua } begin x[i] := j; {Thử cách chọn X[i]} if i < n then {Nếu chưa thử chọn đến X[n]} begin Free[j] := False; {Đánh dấu đỉnh j qua} Try(i + 1); {Để bước thử không chọn phải đỉnh j nữa} Free[j] := True; {Sẽ thử phưng án khác cho X[i] nên bỏ đánh dấu đỉnh vừa thử} end else {Nếu thử chọn đến X[n]} if a[j, X[1]] then PrintResult; {và X[n] lại kề với X[1] ta có chu trình Hamilton} end; end; begin Enter; FillChar(Free, SizeOf(Free), True); {Khởi tạo: Các đỉnh chưa qua} x[1] := 1; Free[1] := False; {Bắt đầu từ đỉnh 1} Assign(fo, OutputFile); Rewrite(fo); Try(2); {Thử cách chọn đỉnh kế tiếp} Close(fo); end Bài tập Bài a) Lập chương trình nhập vào đồ thị chu trình Hamilton có b) Lập chương trình nhập vào đồ thị đường Hamilton có Bài Trong đám cưới Péc-xây An-đrơ-nét có 2n hiệp sỹ Mỗi hiệp sỹ có khơng q n - kẻ thù Hãy giúp Ca-xi-ô-bê, mẹ An-đrơ-nét xếp 2n hiệp sỹ ngồi quanh bàn tròn cho khơng có hiệp sỹ phải ngồi cạnh kẻ thù Mỗi hiệp sỹ cho biết kẻ thù họ đến sân rồng Bài Gray code: Một hình trịn chia thành 2n hình quạt đồng tâm Hãy xếp tất xâu nhị phân độ dài n vào hình quạt, xâu vào hình quạt cho hai xâu hai hình quạt cạnh khác bit Ví dụ với n = 3: 100 000 101 001 111 011 110 Lê Minh Hoàng 010 228 Chuyên đề Bài Thách đố: Bài toán mã tuần: Trên bàn cờ tổng quát kích thước n x n vng (n chẵn ≤ n ≤ 20) Trên có đặt qn mã Qn mã (X1, Y1) di chuyển sang (X2, Y2) ⏐X1-X2⏐.⏐Y1-Y2⏐ = (Xem hình vẽ) Hãy tìm hành trình qn mã từ xuất phát, qua tất ô bàn cờ, ô lần Ví dụ: Với n = 8, xuất phát (3, 3) 45 43 16 47 30 42 17 46 31 60 15 44 48 37 64 18 41 36 59 32 57 35 19 40 49 38 20 50 33 58 25 34 22 39 52 21 51 10 23 61 56 13 28 63 54 11 26 14 29 62 55 12 27 24 53 Với n = 10, ô xuất phát (6, 5) 18 71 100 43 20 69 86 45 22 55 97 42 19 70 99 44 21 24 87 46 72 17 98 95 68 85 88 63 26 23 41 16 96 83 73 80 84 93 81 74 94 89 67 64 90 49 47 62 50 27 79 40 35 82 76 91 66 51 48 36 39 15 12 78 37 75 34 92 77 65 60 57 61 52 28 53 14 33 10 59 56 31 54 29 11 38 13 32 58 55 30 Gợi ý: Nếu coi ô bàn cờ đỉnh đồ thị cạnh nối hai đỉnh tương ứng với hai mã giao chân dễ thấy hành trình quân mã cần tìm đường Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 229 Hamilton Ta xây dựng hành trình thuật tốn quay lui kết hợp với phương pháp duyệt ưu tiên Warnsdorff: Nếu gọi deg(x, y) số ô kề với ô (x, y) chưa qua (kề theo nghĩa đỉnh kề ô kề cạnh) từ ta khơng thử xét hướng có thể, mà ta ưu tiên thử hướng tới có deg nhỏ trước Trong trường hợp có tồn đường đi, phương pháp hoạt động với tốc độ tuyệt vời: Với n chẵn khoảng từ tới 18, với vị trí xuất phát, trung bình thời gian tính từ lúc bắt đầu tới lúc tìm nghiệm < giây Tuy nhiên trường hợp n lẻ, có lúc khơng tồn đường đi, phải duyệt hết khả nên thời gian thực thi lại tồi tệ (Có xét ưu tiên hay xét thứ tự trước thơi Ta thử với n lẻ: 5, 7, … ô xuất phát (1, 2), sau ngồi xem máy tính tốt mồ hơi) Lê Minh Hồng 230 Chun đề §8 BÀI TỐN ĐƯỜNG ĐI NGẮN NHẤT 8.1 ĐỒ THỊ CÓ TRỌNG SỐ Đồ thị mà cạnh gán cho tương ứng với số (nguyên thực) gọi đồ thị có trọng số Số gán cho cạnh đồ thị gọi trọng số cạnh Tương tự đồ thị khơng trọng số, có nhiều cách biểu diễn đồ thị có trọng số máy tính Đối với đơn đồ thị cách dễ dùng sử dụng ma trận trọng số: Giả sử đồ thị G = (V, E) có n đỉnh Ta dựng ma trận vng C kích thước n x n Ở đây: Nếu (u, v) ∈ E C[u, v] = trọng số cạnh (u, v) Nếu (u, v) ∉ E tuỳ theo trường hợp cụ thể, C[u, v] gán giá trị để nhận biết (u, v) cạnh (Chẳng hạn gán +∞, hay 0, -∞ v.v…) Quy ước c[v, v] = với đỉnh v Đường đi, chu trình đồ thị có trọng số định nghĩa giống trường hợp khơng trọng số, có khác độ dài đường khơng phải tính số cạnh qua, mà tính tổng trọng số cạnh qua 8.2 BÀI TOÁN ĐƯỜNG ĐI NGẮN NHẤT Trong ứng dụng thực tế, chẳng hạn mạng lưới giao thông đường bộ, đường thuỷ đường không Người ta khơng quan tâm đến việc tìm đường hai địa điểm mà phải lựa chọn hành trình tiết kiệm (theo tiêu chuẩn khơng gian, thời gian hay chi phí) Khi phát sinh u cầu tìm đường ngắn hai đỉnh đồ thị Bài tốn phát biểu dạng tổng quát sau: Cho đồ thị có trọng số G = (V, E), tìm đường ngắn từ đỉnh xuất phát S ∈ V đến đỉnh đích F ∈ V Độ dài đường ta ký hiệu d[S, F] gọi khoảng cách từ S đến F Nếu không tồn đường từ S tới F ta đặt khoảng cách = +∞ Nếu đồ thị có chu trình âm (chu trình với độ dài âm) khoảng cách số cặp đỉnh khơng xác định, cách vịng theo chu trình số lần đủ lớn, ta đường hai đỉnh chu trình nhỏ số cho trước Trong trường hợp vậy, đặt vấn đề tìm đường (đường khơng có đỉnh lặp lại) ngắn Vấn đề vấn đề phức tạp mà ta không bàn tới Nếu đồ thị khơng có chu trình âm ta chứng minh đường ngắn đường Và biết khoảng cách từ S tới tất đỉnh khác đường ngắn từ S tới F tìm cách dễ dàng qua thuật toán sau: Đại học Sư phạm Hà Nội, 1999-2002 Các thuật toán đồ thị 231 Gọi c[u, v] trọng số cạnh [u, v] Qui ước c[v, v] = với v ∈ V c[u, v] = +∞ (u, v) ∉ E Đặt d[S, v] khoảng cách từ S tới v Để tìm đường từ S tới F, ta nhận thấy tồn đỉnh F1 ≠ F cho: d[S, F] = d[S, F1] + c[F1, F] (Độ dài đường ngắn S->F = Độ dài đường ngắn S->F1 + Chi phí từ F1 tới F) Đỉnh F1 đỉnh liền trước F đường ngắn từ S tới F Nếu F1≡S đường ngắn đường trực cung (S, F) Nếu khơng vấn đề trở thành tìm đường ngắn từ S tới F1 Và ta lại tìm đỉnh F2 khác F F1 để: d[S, F1] = d[S, F2] + c[F2, F1] Cứ tiếp tục vậy, sau số hữu hạn bước, ta suy dãy F, F1, F2, … không chứa đỉnh lặp lại kết thúc S Lật ngược thứ tự dãy cho ta đường ngắn từ S tới F … S F1 F2 F Tuy nhiên, người ta thường không sử dụng phương pháp mà kết hợp lưu vết đường trình tìm kiếm Dưới ta xét số thuật tốn tìm đường ngắn từ đỉnh S tới đỉnh F đơn đồ thị có hướng G = (V, E) có n đỉnh m cung Trong trường hợp đơn đồ thị vô hướng với trọng số khơng âm, tốn tìm đường ngắn dẫn tốn đồ thị có hướng cách thay cạnh hai cung có hướng ngược chiều Lưu ý thuật tốn ln ln tìm đường ngắn đường Input: file văn MINPATH.INP • Dịng 1: Chứa số đỉnh n ( ≤ 100), số cung m đồ thị, đỉnh xuất phát S, đỉnh đích F cách dấu cách • m dịng tiếp theo, dịng có dạng ba số u, v, c[u, v] cách dấu cách, thể (u, v) cung ∈ E trọng số cung c[u,v] (c[u, v] số nguyên có giá trị tuyệt đối ≤ 100) Output: file văn MINPATH.OUT ghi đường ngắn từ S tới F độ dài đường Lê Minh Hồng 232 Chuyên đề 2 20 20 MINPATH.INP 6714 121 20 232 363 20 545 654 MINPATH.OUT Distance from to 4: 15 4 d[t], trái với cách chọn d[u] nhỏ Tất nhiên lần lặp S đỉnh cố định nhãn d[S] = Bước 3: Kết hợp với việc lưu vết đường bước sửa nhãn, thông báo đường ngắn tìm cho biết khơng tồn đường (d[F] = +∞) P_4_08_2.PAS * Thuật toán Dijkstra program Shortest_Path_by_Dijkstra; const InputFile = 'MINPATH.INP'; OutputFile = 'MINPATH.OUT'; max = 100; maxC = 10000; var c: array[1 max, max] of Integer; d: array[1 max] of Integer; Trace: array[1 max] of Integer; Free: array[1 max] of Boolean; n, S, F: Integer; procedure LoadGraph; {Nhập đồ thị, trọng số cung phải số không âm} var i, m, u, v: Integer; fi: Text; begin Assign(fi, InputFile); Reset(fi); ReadLn(fi, n, m, S, F); for u := to n for v := to n if u = v then c[u, v] := else c[u, v] := maxC; for i := to m ReadLn(fi, u, v, c[u, v]); Close(fi); end; procedure Init; {Khởi tạo nhãn d[v], đỉnh coi tự do} var i: Integer; begin Lê Minh Hoàng 236 Chuyên đề for i := to n d[i] := MaxC; d[S] := 0; FillChar(Free, SizeOf(Free), True); end; procedure Dijkstra; {Thuật toán Dijkstra} var i, u, v: Integer; min: Integer; begin repeat {Tìm đỉnh có nhãn tự đỉnh u có d[u] nhỏ nhất} u := 0; := maxC; for i := to n if Free[i] and (d[i] < min) then begin := d[i]; u := i; end; {Thuật toán kết thúc đỉnh tự có nhãn +∞ chọn đến đỉnh F} if (u = 0) or (u = F) then Break; {Cố định nhãn đỉnh u} Free[u] := False; {Dùng đỉnh u tối ưu nhãn đỉnh tự kề với u} for v := to n if Free[v] and (d[v] > d[u] + c[u, v]) then begin d[v] := d[u] + c[u, v]; Trace[v] := u; end; until False; end; procedure PrintResult; {In đường từ S tới F} var fo: Text; begin Assign(fo, OutputFile); Rewrite(fo); if d[F] = maxC then WriteLn(fo, 'Path from ', S, ' to ', F, ' not found') else begin WriteLn(fo, 'Distance from ', S, ' to ', F, ': ', d[F]); while F S begin Write(fo, F, '