1. Trang chủ
  2. » Cao đẳng - Đại học

LÝ THUYẾT ĐỒ THỊ VÀ ỨNG DỤNG TRONG BÀI TOÁN TÌM ĐƢỜNG ĐI NGẮN NHẤT - Full 10 điểm

65 1 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Lý Thuyết Đồ Thị Và Ứng Dụng Trong Bài Toán Tìm Đường Đi Ngắn Nhất
Tác giả Phongsavath Chanthavong
Người hướng dẫn ThS. Lê Thị Nguyên An
Trường học Trường Đại Học Quảng Nam
Chuyên ngành Công Nghệ Thông Tin
Thể loại khóa luận tốt nghiệp
Năm xuất bản 2017
Thành phố Quảng Nam
Định dạng
Số trang 65
Dung lượng 1,8 MB

Cấu trúc

  • PHẦN 1. MỞ ĐẦU (0)
    • 1. Lý do chọn đề tài (7)
    • 2. Mục tiêu của đề tài (7)
    • 3. Đối tƣợng nghiên cứu và phạm vi nghiên cứu (7)
    • 4. Phương pháp nghiên cứu (7)
    • 5. Lịch sử nghiên cứu (8)
    • 6. Đóng góp của đề tài (8)
    • 7. Cấu trúc của đề tài (8)
  • PHÂN 2. NỘI DUNG NGHIÊN CỨU (0)
  • CHƯƠNG 1 TỔNG QUAN VỀ LÝ THUYẾT ĐỒ THỊ (9)
    • 1.1 CÁC KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ (9)
      • 1.1.1 Định nghĩa đồ thị (9)
      • 1.1.2. Định nghĩa đường đi, chu trình, đồ thị liên thông (11)
    • 1.2 CÁC KHÁI NIỆM VỀ ĐƯỜNG ĐI NGẮN NHẤT (14)
      • 1.2.1 Mở đầu (14)
      • 1.2.2 Đường đi ngắn nhất xuất phát từ một đỉnh (15)
      • 1.2.3 Đường đi trong đồ thị không có chu trình (16)
  • CHƯƠNG 2 MỘT SỐ THUẬT TOÁN TÌM ĐƯỜNG ĐI NGẮN NHẤT TRÊN ĐỒ THỊ (18)
    • 2.1. MỘT SỐ KHÁI NIỆM (18)
    • 2.2. ĐƯỜNG ĐI NGẮN NHẤT XUẤT PHÁT TỪ MỘT ĐỈNH (19)
      • 2.2.1 Đường đi ngắn nhất xuất phát từ một đỉnh. Thuật toán Ford-Bellman (19)
      • 2.2.2. Tìm đường đi ngắn nhất bằng thuật toán Dijkstra (21)
    • 2.3. ĐƯỜNG ĐI NGẮN NHẤT GIỮA CÁC CẶP ĐỈNH (23)
      • 2.3.1. Phát biểu bài toán tìm đường đi ngắn nhất (23)
      • 2.3.2. Thuật toán Floyd (24)
  • CHƯƠNG 3 XÂY DỰNG ỨNG DỤNG (28)
    • 3.1. GIỚI THIỆU (28)
    • 3.2. XÂY DỰNG ỨNG DỤNG (28)
      • 3.2.1. Xây dựng lớp thƣ viện Node (28)
      • 3.2.2. Xây dựng lớp thƣ viện Matrix (31)
      • 3.2.3. Xây dựng lớp Edge (40)
    • 3.3. Xây dựng form giao diện của chương trình (45)
    • 3.4. Kết quả chạy chương trình (63)
  • PHẦN 3. KẾT LUẬN (64)
  • PHẦN 4. TÀI LIỆU THAM KHẢO (65)

Nội dung

UBND TỈNH QUẢNG NAM TRƢỜNG ĐẠI HỌC QUẢNG NAM KHOA CÔNG NGHỆ THÔNG TIN -----  ----- PHONGSAVATH CHANTHAVONG LÝ THUYẾT ĐỒ THỊ VÀ ÚNG DỤNG TRONG BÀI TOÁN TÌM ĐƢỜNG ĐI NGẮN NHẤT KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC Quảng Nam, tháng 05 năm 201 7 UBND TỈNH QUẢNG NAM TRƢỜNG ĐẠI HỌC QUẢNG NAM KHOA CÔNG NGHỆ THÔNG TIN -----  ----- KHÓA LUẬN TỐT NGHIỆP ĐẠI HỌC Tên đề tài: LÝ THUYẾT ĐỒ THỊ VÀ ÚNG DỤNG TRONG BÀI TOÁN TÌM ĐƢỜNG ĐI NGẮN NHẤT Sinh viên thực hiện PHONGSAVATH CHANTHAVONG MSSV: 2113011004 CHUYÊN NGÀNH: CÔNG NGHỆ THÔNG TIN KHÓA 201 3 – 2017 Cán bộ hƣớng dẫn ThS LÊ THỊ NGUYÊN AN MSCB: ……… Quảng Nam, tháng 05 năm 201 7 LỜI CẢM ƠN Em xin gửi lời cảm ơn chân thành và sự tri ân sâu sắc đối với các thầy cô của trƣờng Đại học Quảng Nam, đặc biệt là các thầy cô khoa công nghệ thông tin của trƣờng đã tạo điều kiện cho em thực tập ở khoa để có nhiều thời gian cho khóa luận tốt nghiệp Và em cũng xin chân thành cám ơn cô Ths Lê Thị Nguyên An đã nhiệt tình hƣớng dẫn hƣớng dẫn em hoàn thành tốt khóa luận Trong quá trình khóa luận, cũng nhƣ là trong quá trìn h làm bài khóa luận tốt nghiệp, khó tránh khỏi sai sót rất mong các thầy, cô bỏ qua Đồng thời do trình độ lý luận cũng nhƣ kinh nghiệm thực tiễn còn hạn chế nên bài báo cáo không thể tránh khỏi những thiếu sót, em rất mong nhận đƣợc ý kiến đóng góp của quí thầ y, cô để em xin chân thành cảm ơn MỤC LỤC PHẦN 1 MỞ ĐẦU 1 1 Lý do chọn đề tài: 1 2 Mục tiêu của đề tài 1 3 Đối tƣợng nghiên cứu và phạm vi nghiên cứu 1 4 Phƣơng pháp nghiên cứu 1 5 Lịch sử nghiên cứu 2 6 Đóng góp của đề tài 2 7 Cấu trúc của đề tài 2 PHÂN 2 NỘI DUNG NGHIÊN CỨ U 2 CHƢƠNG 1 TỔNG QUAN VỀ LÝ THUYẾT ĐỒ THỊ 3 1 1 CÁC KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ 3 1 1 1 Định nghĩa đồ thị 3 1 1 2 Định nghĩa đƣờng đi, chu trình, đồ thị liên thông 5 1 2 CÁC KHÁI NIỆM VỀ ĐƢỜNG ĐI NGẮN NHẤT 8 1 2 1 Mở đầu 8 1 2 2 Đƣờng đi ngắn nhất xuất phát từ một đỉnh 9 1 2 3 Đƣờng đi trong đồ thị không có chu trình 10 CHƢƠNG 2 MỘT SỐ THUẬT TOÁN TÌM ĐƢỜNG ĐI NGẮN NHẤT TRÊN ĐỒ THỊ 12 2 1 MỘT SỐ KHÁI NIỆM 12 2 2 ĐƢỜNG ĐI NGẮN NHẤT XUẤT PHÁT TỪ MỘT ĐỈNH 13 2 2 1 Đƣờng đi ngắn nhất xuất phát từ một đỉnh Thuật toán Ford -Bellman 13 2 2 2 Tìm đƣờng đi ngắn nhất bằng thuật toán Dijkstra 15 2 3 ĐƢỜNG ĐI NGẮN NHẤT GIỮA CÁC CẶP ĐỈN H 17 2 3 1 Phát biểu bài toán tìm đƣờng đi ngắn nhất 17 2 3 2 Thuật toán Floyd 18 CHƢƠNG 3 XÂY DỰNG ỨNG DỤNG 22 3 1 GIỚI THIỆU 22 3 2 XÂY DỰNG ỨNG DỤNG 22 3 2 1 Xây dựng lớp thƣ viện Node: 22 3 2 2 Xây dựng lớp thƣ viện Matrix: 25 3 2 3 Xây dựng lớp Edge: 34 3 3 Xây dựng form giao diện của chƣơng trình 39 3 4 Kết quả chạy chƣơng trình 57 PHẦN 3 KẾT LUẬN 58 PHẦN 4 TÀI LIỆU THAM KHẢO 59 DANH MỤC HÌNH ẢNH Hình 1 Sơ đồ mạng máy tính 3 Hình 2 Sơ đồ mạng máy tính với đa kênh thoại 4 Hình 4 Mạng máy tính với các kênh thoại một chiều 5 Hình 5 Đƣờng đi trên đồ thị 6 Hình 7 Đồ thị liên thông mạnh g, đồ thị liên thông yếu h 8 Hình 8 Đồ thị không có chu trình 10 Hình 9 Minh họa thuật toán ford_bellman 14 Hình 10 Đồ thị ví dụ 16 Hình 11 M ảng lƣu trữ tạm thời 18 Hình 12 Chƣơng trình demo 39 Hình 13 Kết quả chƣơng trình 57 Trang 1 PHẤN 1 MỞ ĐẦU 1 Lý do chọn đề tài: Lý thuyết đồ thị đƣợc đề xuất từ những năm đầu của thế kỷ 18 bởi nhà toán học ngƣời Thụy Sĩ Leonhard Euler Ông là ngƣời đã sử dụng đồ thị để giải bài toán nổi tiếng về các cây cầu ở thành phố Konigsberg Từ đó lý thuyết đồ thị đƣợc áp dụng rộng rãi và ngày càng khẳng định đƣợc vị trí quan trọng khi đƣợc áp dụng để giải quyết các bài toán thực tế Lý thuyết đồ thị cũng là công cụ đắc lực cho ngành công nghệ thông tin Nó giúp cho chúng ta mô tả một các dễ dàng các bài toán phức tạp thành cụ thể, để từ đó ta có thể mã hóa các bài toán đó vào máy tính Hiện nay có rất nhiều thuật toán để tìm đƣờng đi ngắn nhất trong đồ thị nhƣ: thuật toán Ford -Bellman, th uật toán Dijkstra, thuật toán Floyd để tìm hiểu rõ hơn về các thuật toán này cũng nhƣ ứng dụng hiệu quả các thuật toán này trong thực tế, đó là lý do em chọn đề tài “ Lý thuyết đồ thị và ứng dụng trong bài toán tìm đƣờng đi ngắn nhất để làm đề tài khóa luận tốt nghiệp ” Nội dung của khóa luận bao gồm những phần sau:  Chƣơng 1 : Tổ ng quan v ề lý thuyết đồ th ị  Chƣơng 2 : Mộ t s ố thu ật toán tìm đƣờng đi ngắ n nh ất trên đồ th ị  Chƣơng 3 : Đánh giá và cài đặ t 2 Mục tiêu của đề tài - Hiểu rõ đƣợc những khái niệm cơ bản của lý thuyết đồ thị - Nắm vững một số thuật toán tìm đƣờng đi ngắn nhất của đồ thị - Xây dựng ứng dụng thuật toán Floyd để tìm đƣờng đi ngắn nhất trong thực tế 3 Đối tƣợng nghiên cứu và phạm vi nghiên cứu - Lý thuyế t v ề lý thuyết đồ th ị - M ộ t s ố thu ật toán tìm đƣờng đi ngắ n nh ất trên đồ th ị - Nghiên cứ u thu ật toán Floyd và xây dự ng ứ ng d ụ ng th ự c t ế 4 Phƣơng pháp nghiên cứu - Tìm hiểu thu thập tài liệu liên quan đến lý thuyết đồ thị và một số thuật toán tìm đƣờng đi ngắn nhất trên đồ thị - Kết hợp tìm hiểu so sánh tổng hợp đánh giá các thuật toán tìm đƣờng đi ngắn nhất trên đồ thị - Demo tìm đƣờng đi ngắn nhất tối ƣu Trang 2 5 Lịch sử nghiên cứu - Nội dung đã đƣợc dạy và học ở phần Toán rời rạc - Có nhiều cá nhân cũng nhƣ nhóm nghiên cứu đã chọn kiến thức này làm nội dụng cho đề tài nghiên cứu của họ 6 Đóng góp của đề tài - Cung cấp kiến thức đầy đủ hơn, chi tiết hơn về lý thuyết đồ thị cũng nhƣ các phƣơng pháp tìm đƣờng đi ngắn nhất trên đồ thị - Demo thuật toán tìm đƣờng đi ngắn nhất tối ƣu trong thực tế 7 Cấu trúc của đề tài Chƣơng 1 : Tổng quan về lý tuyết đồ thị  Nghiên cứu, tìm hiể u t ổng quan, trích chọn và trình bày mộ t s ố khái ni ệm cơ bả n v ề lý thuyết đồ th ị Chƣơng 2 : Một số thuật toán tìm đƣờng đi ngắn nhất trên đồ thị  Trình bày mộ t s ố phƣơng pháp tìm đƣờng đi ngắ n nh ất trên đồ th ị Chuong 3 : Đánh giá phƣơng pháp và cài đặt  So sánh đánh giá các phƣơng pháp Demo thuật toán tối ƣu trong tìm đƣờ ng đi ngắ n nh ấ t Trang 3 PH Ầ N 2 N Ộ I DUNG CHƢƠNG 1 T Ổ NG QUAN V Ề LÝ THUYẾT ĐỒ TH Ị 1 1 CÁC KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ 1 1 1 Định nghĩa đồ thị Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối các đỉnh này Chúng ta phân biệt các loại đồ thị khác nhau bởi kiểu và số lƣợng cạnh nối hai đỉnh nào đó của đồ thị Để có thể hình dung đƣợc tại sao lại cần đến c ác loại đồ thị khá c nhau, chúng ta sẽ nêu ví dụ sử dụng chúng để mô tả một mạng máy tín h Giả sử ta có một mạng gồm các máy tính và các kênh điện thoại nối các máy tính này Chúng ta có thể biểu diễn các vị trí đặt máy tính bởi các điểm và các kênh thoại nối chúng bởi các đoạn nối Hình 1 Sơ đồ mạng máy tính Nhận thấy rằng trong sơ đồ mạng máy tính ở hình 1, giữa hai máy tính bất kỳ chỉ cho phép nhiều nhất là một kênh thoại nối chúng, kênh thoại này cho phép liên lạc cả hai chiều và không có máy tính nào lại đƣợc nối với chính nó Sơ đồ mạng máy tính cho trong hình 1 đƣợc gọi là đơn đồ thị vô hướng từ đó ta đi đến một định nghĩa sau: Định nghĩa 1 Đơn đồ thị vô hướng G=(V,E) bao gồm V là tập đỉnh , và E là tập các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh Trong trƣờng hợp giữa hai máy tính nào đó thƣờng xuyên phải truyền tải nhiều thông tin buộc lòng ngƣời ta phải nối hai máy này bởi nhiều kênh thoại Lúc này ta có mô hình mạng máy tính mới đƣợc sinh ra nhƣ sau: Trang 4 H ình 2 Sơ đồ mạng máy tính với đa kênh thoại Từ đó chúng ta có thêm một định nghĩa tiếp theo nhƣ sau: Định nghĩa 2 Đa đồ thị vô hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh Hai cạnh e 1 va e 2 được gọi là cạnh lặp nếu chúng cùng tương ứng với một cặp đỉnh Hình 3 Sơ đồ mạng máy tính với kênh thông báo Rõ ràng mỗi đơn đồ thị đều là đa đồ thị, nhƣng không phải đa đồ thị nào cũng là đơn đồ thị, vì trong đa đồ thị có hai hay nhiều hơn cạnh nối một cặp đỉnh nào đó Trong mạng máy tính có thể có những kênh thoại nối một máy tính nào đó với chính nó (chẳng hạn với mục đích thông báo) Mạng nhƣ vậy đƣợc cho trong hình 3 Nhƣ vậy đa đồ thị không thể mô tả đƣợc mạng nhƣ vậy, bởi vì có những khuyên (cạnh nối một đỉnh vói chính nó) Trong trƣờng hợp này chúng ta cần sử dụng đến khái niệm giả đồ thị vô hƣớng, đƣợc định nghĩa nhƣ sau: Định nghĩa 3 Giả đồ thị vô hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp không có thứ tự gồm hai phần tử (không nhất thiết phải khác nhau) của V gọi là các cạnh Cạnh e được gọi là khuyên nếu có dạng e=(u,u) Trang 5 Các kênh thoại trong mạng máy tính có thể chỉ cho phép truyền tin theo một chiều Chẳng hạn trong hình 4 máy chủ ở Hà Nội chỉ có thể nhận tin từ các máy ở địa phƣơng, có một số máy chỉ có thể gửi tin đi , còn các kênh thoại cho phép truyền tin theo cả hai chiều đƣợc thay thế bởi hai cạnh có hƣớng ngƣợc chiều nhau Hì nh 4 M ạng máy tính với các kênh thoại m ột chiều Ta đi đến định nghĩa sau: Định nghĩa 4 Đơn đồ thị có hướng G=(V,E) bao gồm V là tập các đỉnh và E là tập các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung Nếu trong mạng có thể có đa kênh thoại một chiều, ta sẽ phải sử dụng đến khái niệm đa đồ thị có hướng: Định nghĩa 5 Đa đồ thị có hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung Hai cung e 1 va e 2 tương ứng với cùng một cặp đỉnh được gọi là cung lặp 1 1 2 Định nghĩa đƣờng đi, chu trình, đồ thị liên thông Định nghĩa 1 Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số nguyên dương, trên đồ thị vô hướng G=(V,E) là dãy x o , x 1 , , x n-1 , x n trong đó u=x 0 , v=x n , ( x i , x i+1 )  E , i= 0, 1, 2 , , n-1 Đường đi nói trên còn có thể biểu diễn dưới dạng các cạnh: (x 0 , x 1 ) , ( x 1 , x 2 ), , ( x n-1 , x n ) Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi Đường đi có đỉnh đầu trùng với đỉnh cuối (tức là u=v) được gọi là chu trình Đường đi hay chu trình được gọi là đơn nếu như không có cạnh nào bị lặp lại Ví dụ 1 Trên đồ thị vô hƣớng cho trong hình 1: a,d,c,f,e là đƣờng đi đơn độ dài 4 Còn d,e,c,a không là đƣờng đi do (e,c) không phải là cạnh của đồ thị Dãy b,c,f,e,b Trang 6 là chu trình độ dài 4 Đƣờng đi a,b,e,d,a,b có độ dài là 5 không phải là đƣờng đi đơn, do cạnh (a,b) có mặt trong nó hai lần Hình 5 Đường đi trên đồ thị Khái niệm đƣờng đi và chu trình trên đồ thị có hƣớng đƣợc định nghĩa hoàn toàn tƣơng tự nhƣ trƣờng hợp đồ thị vô hƣớng, chỉ khác là ta chú ý đến hƣớng trên các cung Định nghĩa 2 Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số nguyên dương, trên đồ thị có hướng G=(V,A) là dãy x o , x 1 , , x n-1 , x n trong đó u=x 0 , v=x n , ( x i , x i+1 )  A , i= 0, 1, 2 , , n-1 Đường đi nói trên còn có thể biểu diễn dưới dạng các cung: (x 0 , x 1 ) , ( x 1 , x 2 ), , ( x n-1 , x n ) Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi Đường đi có đỉnh đầu trùng với đỉnh cuối (tức là u=v) được gọi là chu trình Đường đi hay chu trình được gọi là đơn nếu như không có cung nào bị lặp lại V í dụ 2 Trên đồ thị có hƣớng cho trong hình 1: a,d,c,f,e là đƣờng đi đơn độ dài 4 Còn d,e,c,a không là đƣờng đi do (e,c) không phải là c ung của đồ thị Dãy b ,c,f,e,b là chu trình độ dài 4 Đƣờng đi a,b,e,d,a,b có độ dài là 5 không phải là đƣờng đi đơn, do cung (a,b) có mặt trong nó hai lần Xét một mạng máy tính Một câu hỏi đặt ra là hai máy tính bất kỳ trong mạng này có thể trao đổi đƣợc thông tin với nhau hoặc trực tiếp qua kênh nối chúng hợăc thông qua một hoặc vài máy tính trung gian trong mạng? Nếu sử dụng đồ thị để biểu diễn mạng máy tính này (trong đó các đỉnh của đồ thị tƣơng ứng với các máy tính, còn các cạnh tƣơng ứng với các kênh nối) câu hỏi đó đƣợc phát biểu trong ngôn ngữ đồ thị nhƣ sau: Tồn tại hay chăng đƣờng đi giữa mọi cặp đỉnh của đồ thị ? Định nghĩa 3 Đồ thị vô hướng G=(V,E) được gọi là liên thông nếu luôn tìm được đường đi giữa hai đỉnh bất kỳ của nó Nhƣ vậy hai máy tính bất kỳ trong mạng có thể trao đổi thông tin đƣợcvới nhau khi và chỉ khi đồ thị tƣơng ứng với mạng này là đồ thị liên thông Trang 7 V í dụ 3 Trong hình 6: Đồ thị G là liên thông, đồ thị H là không liên thông Hình 6 Đồ thị liên thông G và đồ thị H gồm 3 thành phần liên thông H 1 ,H 2 ,H 3 Định nghĩa 4 Ta gọi đồ thị con của đồ thị G=(V,E) là đồ thị H=(W,F), trong đó W  V và F  E Trong trƣờng hợp đồ thị là không liên thông, nó sẽ rã ra thành một số đồ thị con liên thông đôi một không có đỉnh chung Những đồ thị con liên thông nhƣ vậy ta sẽ gọi là các thành phần liên thông của đồ thị Trong mạng máy tính có thể có những má y ( những kênh nối) mà sự hỏng hóc của nó có thể ảnh hƣởng đến việc trao đổi thông tin trong mạng Các khái niệm tƣơng ứng với tình huống này đƣợc đƣa ra trong định nghĩa sau Định nghĩa 5 Đỉnh v được gọi là đỉnh rẽ nhánh nếu việc loại bỏ v cùng với các cạnh liên thuộc với nó khỏi đồ thị làm tăng số thành phần liên thông của đồ thị Cạnh e được gọi là cầu nếu việc loại bỏ nó khỏi đồ thị làm tăng số thành phần liên thông của đồ thị V í dụ 5 trong đồ thị G ở hình 2, đỉnh d và e là đỉnh rẽ nhánh, còn các cạnh (d,g) và (e,f) là cầu Đối với đồ thị có hƣớng có hai khái niệm liên thông phụ thuộc vào việc ta có xét đến hƣớng trên các cung hay không Định nghĩa 6 Đồ thị có hướng G=(V,A) được gọi là liên thông mạnh nếu luôn tìm được đường đi giữa hai đỉnh bất kỳ của nó Định nghĩa 7 Đồ thị có hướng G=(V,A) được gọi là liên thông yếu nếu đồ thị vô hướng tương ứng với nó là đồ thị vô hướng liên thông Rõ ràng nếu đồ thị là liên thông mạnh thì nó cũng là liên thông yếu, nhƣng điều ngƣợc lại là không luôn đúng, nhƣ chỉ ra trong v í dụ dƣới đây Trang 8 V í dụ 6 Trong hình 3 đồ thị G là liên thông mạnh, còn H là liên thông yếu nhƣng không là liên thông mạnh Hình 7 Đồ thị liên thông mạnh G, đồ thị liên thông yếu H 1 2 CÁC KHÁI NIỆM VỀ ĐƢỜNG ĐI NGẮN NHẤT 1 2 1 Mở đầu Trong phần này chúng ta chỉ xét đồ thị có hƣớng G=(V,E) và |V|=n,|E|=m với các cung đƣợc gán trọng số, nghĩa là, mỗi cung (u,v)  E của nó đƣợc đặt tƣơng ứng với một số thực a(u,v) gọi là trọng số của nó Chúng ta sẽ đặt a(u,v)=  , nếu (u,v)  E Nếu dãy v 0 , v 1 , , v p là một đƣờng đi trên G, thì độ dài của nó đƣợc định nghĩa là tổng sau: tức là, độ dài của đƣờng đi chính là tổng các trọng số trên các cung của nó (Chú ý rằng nếu chúng ta gán trọng số cho tất cả các cung đều bằng 1, thì ta thu đƣợc định nghĩa độ dài đuờng đi nhƣ là số cung của đƣờng đi Bài toán tìm đƣờng đi ngắn nhất trên đồ thị dƣới dạng tổng quát có thể đƣợc phát biểu dƣới dạng tổng quát nhƣ sau : Tìm đƣờng đi có độ dài nhỏ nhất từ một đỉnh xuất phát s  V đến đỉnh cuối (đích) t  V Đƣờng đi nhƣ vậy sẽ gọi là đường đi ngắn nhất từ s đến t còn độ dài của nó sẽ kí hiệu là d(s,t) và còn gọi là khoảng cách từ s đến t (khoảng cách định nghĩa nhƣ vậy có thể là số âm ) Nếu nhƣ không tồn tại đƣờng đi từ s đến t thì ta đặt d(s,t)=  từ đó ta thấy chu trình trong đồ thị có độ dài dƣơng, thì trong đƣờng đi ngắn nhất không có đỉnh nào lặp lại (đƣờng đi nhƣ thế gọi là đường đi cơ bản ) Trang 9 Mặt khác, n ếu trong đồ thị có chu trình với độ dài âm (gọi là chu trình âm ) thì khoảng cách giữa 1 số cặp đỉnh nào đó của đồ thị có thể là không xác định, bởi vì, bằng cách đi vòng theo chu trình này một số đủ lớn lần, ta có thể chỉ ra đƣờng đi giữa các đỉnh này có độ dài nhỏ hơn bất kì số thực cho trƣớc nào Trong truờng hợp nhƣ vậy, có thể đặt vấn đề tìm đƣờng đi cơ bản ngắn nhất, tuy nhiên bài toán đặt ra sẽ trở nên phức tạp hơn rất nhiều, bởi vì nó chứa bài toán xét sự tồn tại đƣờng đi Hamilto n trong đồ thị nhƣ là một trƣờng hợp riêng Trƣớc hết cần chú ý rằng nếu biết khoảng cách từ s đến t, thì đƣờng đi ngắn nhất từ s đến t, trong trƣờng hợp trọng số không âm, có thể tìm một cách dễ dàng Để tìm đƣờng đi, chỉ cần chú ý là đối với cặp đỉnh s,t  V tuỳ ý (s  t ) luôn tìm đƣợc đỉnh v sao cho: d(s,t) = d(s,v) + a(v,t) Th ật vậy đỉnh v nhƣ vậy chính là đỉnh đi trƣớc đỉnh t trong đƣờng đi ngắn nhất từ s đến t Tiếp theo ta có thể tìm đƣợc u sao cho d(s,v)=d(s,u)+a(u,v), Từ giả thiết về tính không âm của các trọng số dễ dàng suy ra rằng dãy t,v,u không chứa đỉnh lặp lại và kết thúc ở đỉnh s Rõ ràng dãy thu đƣợc xác định đƣờng đi ngắn nhất từ s đến t 1 2 2 Đƣờng đi ngắn nhất xuất phát từ một đỉnh Phần lớn các thuật toán tìm khoảng cá ch giữa hai đỉnh s và t đƣợc xây dựng nhờ kỹ thuật tính toán mà ta có thể mô tả nhƣ sau: từ ma trận trọng số a[u,v],u,v  V, ta tính cận trên d[v] của khoảng cách từ s đến tất cả các đỉnh v  V Mỗi khi phát hiện d[u]+ a[u,v] L[i] + C[i, j] then 14 begin 15 L[j] := L[i] + C[i, j] ; 16 Truoc[j] := i ; 17 end ; 18 end ; 19 end ; Ví dụ : Tìm đƣờng đi ngắn nhất trong đồ thị sau Hình 10 : Đồ thị ví dụ Bảng 1: Bƣớc thứ nhất của tìm đƣờng đi ngắn nhất 1 2 3 4 5 6 (0,1) (7,1) (1,1)* (  ,1) (  ,1) (  ,1) (0,1) (6,3)* (1,1) (  ,1) (6,3) (8,3) (0,1) (6,3) (1,1) (10,2) (6,3)* (7,2) (0,1) (6,3) (1,1) (10,2) (6,3) (7,2)* (0,1) (6,3) (1,1) (10,2)* (6,3) (7,2) (0,1) (6,3) (1,1) (10,2) (6,3) (7,2) Trang 17 Bảng 2: Bƣớc thứ hai của tìm đƣờng đi ngắn nhất 0 1 2 3 4 5 6 7 0 0 2 0 0 0 1 0 0 1 2 0 2 2 4 0 0 0 2 0 2 0 0 3 0 0 1 3 0 2 0 0 4 3 0 0 4 0 4 3 4 0 0 7 0 5 1 0 0 3 0 0 5 0 6 0 0 0 0 7 5 0 6 7 0 0 1 0 0 0 6 0 2 3 ĐƢỜNG ĐI NGẮN NHẤT GIỮA CÁC CẶP ĐỈN H 2 3 1 Phát biểu bài toán tìm đƣờng đi ngắn nhất Cho đồ th ị có trọ ng s ố G = (V, E), s và t là hai đỉ nh c ủa đồ th ị Tìm đƣờng đi ng ắ n nh ấ t t ừ trên đồ th ị t ừ s đến t độ dài ký hiệu là d(s, t) Hãy tìm đƣờng đi có tổ ng tr ọ ng s ố nh ỏ nh ấ t t ừ s đế n t Điề u ki ện để bài toán có lờ i gi ả i, ph ả i t ồ n t ại đƣờng đi từ s đế n t: - Đồ th ị vô hƣớng liên thông - Đồ th ị có hƣớng liên thông mạ nh - Đồ th ị vô hƣớng, s và t nằm trong cùng mộ t m ột thành phần liên thông - Đồ th ị có hƣớng, có tồ n t ại đƣờng đi từ s đế n t - Trong đồ th ị không tồ n t ại chu trình âm - Đồ th ị có hƣớng: không tồ n t ại chu trình âm - Đồ th ị vô hƣớng: không tồ n t ạ i c ạnh âm V ậ y: Ý tƣở ng chung c ủ a thu ật toán tìm đƣờng đi ngắ n nh ấ t - Dò tìm bằng cách thử qua các đỉ nh trung gian Trang 18 - N ếu phát hiện đƣờng đi qua đỉ nh trung gian ng ắn hơn đƣờng đi hiệ n t ạ i thì sẽ c ậ p nh ập đƣờng đi mới, đồ ng th ờ i ch ỉ nh s ửa thông tin liên quan - S ử d ụ ng hai m ảng để lƣu trữ t ạ m th ờ i: M ảng d[v]: Lƣu trữ độ dài đƣờng đi ngắ n nh ấ t hi ệ n t ạ i t ừ s đế n v M ảng T[v]: Lƣu trữ đỉ nh n ằm trƣớc v trên đƣờng đi ngắ n nh ấ t hi ệ n t ạ i Hình 11 : Mảng lƣu trữ t ạ m th ờ i 2 3 2 Thuật toán Floyd Gi ả i thu ậ t tìm độ dài đƣờng đi ngắ n nh ấ t gi ữ a m ọ i c ặp đỉnh trong đồ th ị có hƣớ ng liên thông có trọ ng s ố (không bắ t bu ộ c ) + Đầu vào Đồ th ị liên thông G = (V, E), V = { } , có tr ọ ng s ố w(i,j) v ớ i m ọ i cung (i,j) + Đầ u ra Ma tr ậ n D = [ ] trong đó d(i,j) là chi ề u dài đƣ ờ ng đi ng ắ n nh ấ t t ừ i đ ế n j v ớ i m ọ i c ặ p (i,j) +Phương pháp (1) Bƣớ c kh ở i t ạo: Kí hiệ u là ma tr ậ n xu ất phát = [ ] Trong đó : (i,j) = w(i,j) n ế u t ồ n t ại cung (i,j) và (i,j) = +∞ nếu không tồ n t ạ i cung (i,j) đặ c bi ệ t n ếu không có khuyên tại i thì (i,i) = +∞) Gán k:=0 (2) Ki ể m tra k ết thúc: Nế u k = n, k ết thúc D = là ma trận độ dài đƣờng đi ng ắ n nh ất Ngƣợ c l ại tăng k lên 1 đơn vị (k: = k+1) và sang (3) (3) Tính ma trậ n theo : V ớ i m ọ i c ặ p (i,j), i=1 n, j=1 n th ự c hi ệ n: N ế u (i,j) > (i,k) + (k,j) thì đặ t Formatted: Centered, Level 1, Indent: First line: 1 cm, Space Before: 0 pt, After: 0 pt Trang 19 dk(i,j) := dk-1(i,k) + dk-1(k,j) Ngƣợ c l ại đặ t dk(i,j): = (i,j) Quay l ại bƣớ c (2) Ví dụ: Xét đồ thị sau Áp dụng thuật toán Floyd ta có: Ma trận khoảng cách xuất phát D o là (các ô trống là  ): D o = Đỉnh 1 2 3 4 5 6 1 7 2 2 4 1 3 3 4 4 5 2 2 6 1 Từ ma trận d o , theo thuật toán, ta xây dựng các ma trận tiếp theo nhƣ sau ( các ô gạch dƣới có giá trị thay đổi) D 1 = Đỉnh 1 2 3 4 5 6 1 7 2 2 4 1 3 3 4 4 5 2 9 2 4 6 1 D 2 = Đỉnh 1 2 3 4 5 6 1 7 11 2 8 2 4 1 3 3 7 2 4 3 3 6 2 1 1 5 4 2 4 2 1 Trang 20 4 4 8 5 5 2 9 2 4 10 6 1 5 2 D 3 = Đỉnh 1 2 3 4 5 6 1 7 11 2 8 14 2 4 1 7 3 3 4 4 8 5 11 5 2 9 2 4 10 5 6 1 5 2 8 D 4 = Đỉnh 1 2 3 4 5 6 1 6 10 2 7 13 2 4 1 7 3 3 4 4 8 5 11 5 2 8 2 4 9 5 6 1 5 2 8 D 5 = Đỉnh 1 2 3 4 5 6 1 9 6 9 2 7 12 2 3 9 3 5 1 6 3 3 4 7 4 7 9 5 10 5 2 8 2 4 9 5 6 4 1 4 6 2 7 D =D 6 = Đỉnh 1 2 3 4 5 6 1 9 6 9 2 7 12 Trang 21 2 3 7 3 5 1 6 3 7 4 7 9 5 3 4 7 4 7 9 5 10 5 2 6 2 4 7 5 6 4 1 4 6 2 7 Cuối cùng, D là ma trận khoảng cách ngắn nhất giữa các đỉnh Theo hệ quả ta thấy đồ thị liên thông và chứa chu trình Trang 22 CHƢƠNG 3 XÂY DỰNG ỨNG DỤNG 3 1 GIỚI THIỆU Để minh họa cho thuật toán Floyd – tìm đƣờng đi ngắn nhất giữa mọi cặp đỉnh của đồ thị, chúng tôi sử dụng ngôn ngữ lập trình C# trong bộ Microsoft Visual Studio 2010 để xây dựng ứng dụng minh họa 3 2 XÂY DỰNG ỨNG DỤNG 3 2 1 Xây dựng lớp thƣ viện Node: Xây dựng lớp thƣ viện Node cs nhằm hỗ trợ việc vẽ đỉnh của độ thị Mã nguồn: namespace FloydDemo { class Node : Control { public char DisplayName; public int Index { get; set; } public bool Selected; int _alpha = 0; bool _isRevoming; bool _isCreating; public Node() { this Size = new Size(1, 1); this BackColor = Color Wheat; } //Hiệu ứng khi nhấn tạo đỉnh public void DoCreatingAnimation() { this _isCreating = true; while (_alpha < 240) { this Inflate(1); Trang 23 _alpha += 20; this Refresh(); Thread Sleep(10); } this _isCreating = false; Invalidate(); } public void Inflate(int size) { // if (this Width + size < GraphUI NODE_DIAMETER) // return; Rectangle rect = this Bounds; rect Inflate(size, size); this Bounds = rect; Invalidate(); } public void DoRemovingAnimation() { this _isRevoming = true; while (_alpha > 0) { this Inflate(1); _alpha - = 10; this Refresh(); Thread Sleep(10); } this _isRevoming = false; } //Sự kiện nhấn chuột protected override void OnMouseDown(MouseEventArgs e) { Trang 24 base OnMouseDown(e); Invalidate(); } protected override void OnLostFocus(EventArgs e) { base OnLostFocus(e); Inv alidate(); } protected override void OnPaint(PaintEventArgs e) { Brush foreBrush = new SolidBrush(this ForeColor); // base OnPaint(e); string text = DisplayName ToString(); e Graphic s SmoothingMode = SmoothingMode AntiAlias; Rectangle rect = this ClientRectangle; rect Inflate( - 1, - 1); if (_isCreating || _isRevoming) { Color c = Color FromArgb(_alpha, Color Red); e Graphics FillEllipse(new SolidBrush(c), rect); } else { Pen p = new Pen(this ForeColor); if (this Selected) { p = new Pen(Color Red, 3 ); } e Graphics DrawEllipse(p, rect); Trang 25 } rect Inflate(1, 1); //vẽ chữ vào SizeF s = e Graphics MeasureString(text, this Font); e Graphics DrawString(text, this Font, foreBrush, (this Width - s Width) / 2, (this Height - s Height) / 2); GraphicsPath path = new GraphicsPath(); path AddEllipse(rect); this Region = new System Drawing R egion(path); } public override string ToString() { return DisplayName ToString(); } } } 3 2 2 Xây dựng lớp thƣ viện Matrix : Xây dựng lớp thƣ viện Matrix cs để vẽ lên ma trận của đồ thị Đồng thời, cài đặt thuật toán Floyd vào trong lớp này để sử dụng tìm đƣờng đi ngắn nhất giữa mọi cặp đỉnh của đồ thị Mã nguồn: namespace FloydDemo { class Matrix : Control { const int OFFSET = 20; const int HANDLE_SIZE = 6;//Mặc định nên để là 6 Point _p; Trang 26 Point _pRightBottom; int[,] _data; public FloydCell[,] FloydData; float _size; // vị trí của handles Rectangle _rectHandle1, _rectHandle2, _rectHandle3, _rectHandle4; int _handleIndex = - 1; bool _selected = false; bool _resizing = fa lse; public Matrix() { _rectHandle1 = new Rectangle(0, 0, HANDLE_SIZE, HANDLE_SIZE); this MinimumSize = new Size(20, 20);//Mặc định là 20x20 this Size = new Size(160, 160);//Mặc định mình nên gán nó 160x160 this DoubleBuffered = true; } public void Reset() { _data = null; FloydData = null; } public int[,] Data { get { return _data; } set { _data = value; _size = (this Width - OFFSET) / Data GetLength(0); Floyd(); Invalidate(); Trang 27 } } //Thuật toán Floyd //Áp dụng theo giáo trình mà cô An gửi public void Floyd() { if (Data == null) return; int n = Data GetLength(0); FloydData = new FloydCell[n, n]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) FloydData[i, j] = new FloydCell(Data[i, j]); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (FloydData[j, i] Value > 0) { for (int k = 0; k < n; k++) { if (FloydData[i, k] Value > 0) { if (FloydData[j, k] Value < 0 || FloydData[j, i] Value + FloydData[i, k] Value < FloydData[j, k] Value) { FloydData[j, k] Value = FloydData[j, i] Value + FloydData[i, k] Value; Trang 28 FloydData[j, k] Previous = i; } } } } } } } protected override void OnMouseHover(EventArgs e) { _selected = true; Invalidate(); base OnMouseHover(e); } protected override void OnMouseLeave(EventArgs e) { _selected = false; Invalidate(); base OnMouseLeave(e); } protected override void OnMouseDown(MouseEventArgs e) { if (e Button == MouseButtons Left) { _p = e Location; Invalidate(); _resizing = true; Rectangle cursor = new Rectangle(e Location, new Size(0, 0)); _pRightBottom = new Point(this Right, this Bottom); // Kiểm tra cursor có nằm trên handle nào không -- > Trang 29 if (_rectHandle1 IntersectsWith(cursor)) _handleIndex = 0; else if (_rectHandle2 IntersectsWith( cursor)) _handleIndex = 1; else if (_rectHandle3 IntersectsWith(cursor)) _handleIndex = 2; else if (_rectHandle4 IntersectsWith(cursor)) _handleIndex = 3; else _resizing = false; } base OnMouseDown(e); } protected override void O nMouseMove(MouseEventArgs e) { if (e Button == MouseButtons Left) { if (_resizing) { // Thay đổi vị trí và kích thƣớt đƣa vào handle đƣợc dùng if (_handleIndex == 0) { this Cursor = Cursors SizeNWSE; this Location = this Parent PointToClient(this PointToScreen(e Location)); this Width = _pRightBottom X - this Left; this Height = _pRightBottom Y - this Top; } else if (_handleIndex == 1) { Trang 30 this Cursor = Cursors SizeNESW; this Width = e X; this Top = this Parent PointToClient(this PointToScreen(e Location)) Y; this Height = _pRightBottom Y - this Top; } else if (_handleIndex == 2) { this Cursor = Cursors SizeNWSE; this Width = e X; this Height = e Y; } else if (_handleIndex == 3) { this Cursor = Cursors SizeNESW; this Left = this Parent PointToClient(this PointToScreen(e Location)) X; this Width = _pRightBottom X - this Left; this Height = e Y; } } else { this Cursor = Cursors SizeAll; Point p = this Parent PointToClient(this PointToScreen(e Location)); p X - = _p X; p Y - = _p Y; this Location = p; } Invalidate(); Trang 31 } base OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { this Cursor = Cursors Arrow; base OnMouseUp(e); } protected override void OnSizeChanged(EventArgs e) { base OnSizeChanged(e); } protected override void OnResize(EventArgs e) { if (Data != null) _size = (this Width - OFFSET) / Data GetLength(0); this Height = this Width; _rectHandle2 = new Rectangle(this Width - HANDLE_SIZE - 1, 0, HANDLE_SIZE, HANDLE_SIZE); _rectHandle3 = new Rectangle( this Width - HANDLE_SIZE - 1, this Height - HANDLE_SIZE - 1, HANDLE_SIZE, HANDLE_SIZE); _rectHandle4 = new Rectangle(0, this Height - HANDLE_SIZE - 1, HANDLE_SIZE, HANDLE_SIZE); Refresh(); base OnResize(e); } protected override void OnPaint(PaintEventArgs e) { if (Data == null) return; Trang 32 DrawMatrix(Data, e Graphics); if (_selected) { // vẽ handles e Graphics FillRectangle(Brushes White, _rectHandle1); e Graphics FillRectangle(Brushes White, _rectHandle2); e Graphics FillRectangle(Brushes White, _rectHandle3); e Graphics FillRectangle(Brushes White, _rectHandle4); e Graphics DrawRectangle(Pens Gray, _rectHandle1); e Graphics DrawRectangle(Pens Gray, _rectHandle2); e Graphics DrawRectangl e(Pens Gray, _rectHandle3); e Graphics DrawRectangle(Pens Gray, _rectHandle4); } e Graphics DrawRectangle(Pens Black, 0, 0, this Width - 1, this Height - 1); base OnPaint(e); } void DrawMatrix(int[,] array, Graphics g) { int n = array GetLength(0); for (int i = 0; i < n; i++) { float x = i * _size + OFFSET; string s = ((char)(i + ''''A'''')) ToString(); Trang 33 g DrawString(s, this Font, Brushes Blue, new PointF(0, x)); g DrawString(s, this Font, Brushes Blue, new PointF(x, 0)); g DrawLine(Pens Gray, x, 0, x, this Height); g DrawLine(Pens Gray, 0, x, this Width, x); for (int j = 0; j < n; j++) { string v; if (array[i, j] < 0) { v = " - "; if (FloydData != null) { if (FloydData[i, j] Value > 0) { v = FloydData[i,j] Value ToString(); g FillRectangle(Brushes LightGray, new RectangleF(x + 1, j * _size + OFFSET + 1, _size - 1, _size - 1)); g DrawString(v, this Font, Brushes Red, new Poi ntF(x, j * _size + OFFSET)); continue; } } } else v = array[i, j] ToString(); Trang 34 g DrawString(v, this Font, Brushes DarkMagenta, new PointF(x, j * _size + OFFSET)); } } } } struct FloydCell { public int Previous; public int Value; public FloydCell(int value) : this( - 1, value) { } public FloydCell(int previous, int value) { this Previous = previous; this Value = value; } } } 3 2 3 Xây dựng lớp Edge: Xây dựng lớp Edge cs nhằm hỗ trợ việc vẽ cạnh của đồ thị Mã nguồn: namespace FloydDemo { [Serializable] class EdgeCollection : IEnumerable { List _list; public int SelectedIndex { Trang 35 get; set; } public Edge SelectedItem { get { return _list[this SelectedIndex]; } } public EdgeCollection() { _list = new List(); } public bool Add(Edge edge) { if (!_list Contains(edge)) { Edge newEdge = new Edge(edge End, edge Start); if (_list Contains(newEdge)) { edge = _list[_list IndexOf(newEdge)]; edge IsUndirected = true; } else { _list Add(edge); } return true; } return false; } Trang 36 public void Clear() { _list Clear(); } public bool Contains(Edge edge) { return _list Contains(edge); } public Edge this[int index] { get { return _list[index]; } } public bool Contains(Edge edge, bool checkInverted) { if (_list Contains(edge)) return true; if (checkInverted) return _lis t Contains(new Edge(edge End, edge Start)); return false; } public void RemoveAt(int index) { System Threading Thread Sleep(100); _list RemoveAt(index); } public int Count { get { return _list Count; } } public IEnumerator GetEnumerator() { return _list GetEnumerator(); } Trang 37 System Collections IEnumerator System Collections IEnumerable GetEnumerator() { return _list GetEnumerator(); } } [Serializable] class Edge { private const float EPSILON = 2f; public int S tart; public int End; public bool IsUndirected; public bool IsRemoving; public Edge(int start, int end) { this Start = start; this End = end; this IsUndirected = false; } public static bool Contains(PointF start, PointF end, PointF p) { if (p X < Math Min(start X, end X) || p X > Math Max(start X, end X) || p Y < Math Min(start Y, end Y) || p Y > Math Max(start Y, end Y)) return false; var dx = end X - start X; var dy = end Y - start Y; var v1 = new Vector2D(dx, dy) Length; Trang 38 float cx = p X - start X; float cy = p Y - start Y; var v2 = new Vector2D(cx, cy) Length; var v3 = new Vector2D(p X - end X, p Y - end Y) Length; var pp = (v1 + v2 + v3) / 2; var s = Math Sqrt(pp * (pp - v1) * (pp - v2) * (pp - v3)); var h = s * 2 / v1; Console WriteLine(h); return h < EPSILON; } public override bool Equals(Object obj) { if (!(obj is Edge)) return false; Edge con = (Edge)obj; if (this Start == con Start && this End == con End) return true; if (this IsUndirected && this Start == con End && this End == con Start) return true; ret urn false; } public override int GetHashCode() { return Start ^ End; } } } Trang 39 3 3 Xây dựng form giao diện của chƣơng trình Hình 12 : Chương trình demo Xây dựng form gồm các điều khiển: ComboBox cboFrom: Lựa chọn đỉnh bắt đầu ComboBox cboTo: Lựa chọn đỉnh đích Button cmduongDi: Tìm đƣờng đi ngắn nhất từ đỉnh bắt đầu đến đỉnh đích và các điều khiển liên quan khác Mã nguồn: private void InitializeComponent() { // cmdDuongDi // this cmdDuongDi ForeColor = System Drawing Color Blue; this cmdDuongDi Image = ((System Drawing Image)(resources GetObject("cmdDuongDi Image" ))); Trang 40 this cmdDuongDi ImageAlign = Sys tem Drawing ContentAlignment MiddleLeft; this cmdDuongDi Location = new System Drawing Point(16, 144); this cmdDuongDi Margin = new System Windows Forms Padding(4); this cmdDuongDi Name = "cmdDuongDi"; this c mdDuongDi Size = new System Drawing Size(196, 42); this cmdDuongDi TabIndex = 3; this cmdDuongDi Text = "Đƣờng đi ngắn nhất"; this cmdDuongDi TextAlign = System Drawing ContentAlignment MiddleRight; this cmdD uongDi UseVisualStyleBackColor = true; this cmdDuongDi Click += new System EventHandler(this cmdDuongDi_Click); // // cmdXoaHet // this cmdXoaHet ForeColor = System Drawing Color Blue; this cmdXoaHet Image = ((System Drawing Image)(resources GetObject("cmdXoaHet Image") )); this cmdXoaHet ImageAlign = System Drawing ContentAlignment MiddleLeft; this cmdXoaHet Location = new System Drawing Point(119, 236); this cmdXoaHet Margin = new System Windows Forms Padding(4); this cmdXoaHet Name = "cmdXoaHet"; this cmdXoaHet Size = new System Drawing Size(112, 42); this cmdXoaHet TabIndex = 4; this cmdXoaHet Text = "Xóa tất cả"; Trang 41 this cmdXoaHet TextAlign = System Drawing ContentAlignment MiddleRight; this cmdXoaHet UseVisualStyleBackColor = true; this cmdXoaHet Click += new System EventHandler(this cmdXoaHet_Click); // // panel1 // this panel1 Anchor = ((System Windows Forms AnchorStyles)(((System Windows Forms An chorStyles Top | System Windows Forms AnchorStyles Bottom) | System Windows Forms AnchorStyl es Left))); this panel1 BorderStyle = System Windows Forms BorderStyle Fixed3D; this panel1 Controls Add(this linkLabel3); this panel1 Controls Add(this linkLabel2); this panel1 Controls Add(this panel2); this panel1 Controls Add(this linkLabel1); this panel1 Controls Add(this cmdXoaDuongDi); this panel1 Controls Add(this cmdXoaDuongDiCuoi); this panel1 Controls Add(this groupBox1); this panel1 Controls Add(this cmdDuongDi); this panel1 Controls Add(this cmdXoaHet); this panel1 Location = new System Drawing Point(3, 41); this panel1 Margin = new System Windows Forms Padding(4); this panel1 Name = "panel1"; this panel1 Size = new System Drawing Size(240, 491); this panel1 TabIndex = 7; // // linkLabel3 Trang 42 // this linkLabel3 AutoSize = true; this linkLabel3 Font = new System Drawing Font("Tahoma", 9 75F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); this linkLabel3 Location = new System Drawing Point(77, 443); this linkLabel3 Name = "link Label3"; this linkLabel3 Size = new System Drawing Size(126, 16); this linkLabel3 TabIndex = 18; this linkLabel3 TabStop = true; this linkLabel3 Text = " - Nguyễn Đức Chung"; this linkLabel3 LinkCl icked += new System Windows Forms LinkLabelLinkClickedEventHandler(this lin kLabel3_LinkClicked); // // linkLabel2 // this linkLabel2 AutoSize = true; this linkLabel2 Font = new System Drawing Font("Tahoma", 9 75F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); this linkLabel2 Location = new System Drawing Point(5, 467); this linkLab el2 Name = "linkLabel2"; this linkLabel2 Size = new System Drawing Size(229, 16); this linkLabel2 TabIndex = 17; this linkLabel2 TabStop = true; this linkLabel2 Text = "GV hƣớng dẫn: ThS Lê Thị Nguyên An"; Trang 43 this linkLabel2 LinkClicked += new System Windows Forms LinkLabelLinkClickedEventHandler(this lin kLabel2_LinkClicked); // // panel2 // this panel2 BorderStyle = System Windows Forms BorderStyle F ixedSingle; this panel2 Controls Add(this chkVoHuong); this panel2 Controls Add(this label3); this panel2 Controls Add(this cboTo); this panel2 Controls Add(this cboFrom); this panel2 Controls Add(this label2); this panel2 Controls Add(this label1); this panel2 Location = new System Drawing Point(5, 3); this panel2 Name = "panel2"; this panel2 Size = new System Drawing Size(219, 122); this panel2 TabIndex = 16; // // chkVoHuong // this chkVoHuong Location = new System Drawing Point(28, 85); this chk VoHuong Margin = new System Windows Forms Padding(4); this chkVoHuong Name = "chkVoHuong"; this chkVoHuong Size = new System Drawing Size(154, 29); this chkVoHuong TabIndex = 17; this chkVoHuong Text = "Đồ th ị vô hƣớng"; this chkVoHuong UseVisualStyleBackColor = true; this chkVoHuong CheckedChanged += new System EventHandler(this chkVoHuong_CheckedChanged); Trang 44 // // label3 // this label3 Au toSize = true; this label3 Font = new System Drawing Font("Tahoma", 11 25F, System Drawing FontStyle Bold, System Drawing GraphicsUnit Point, ((byte)(0))); this label3 ForeColor = System Drawing Color Red; this label3 Lo cation = new System Drawing Point(5, 6); this label3 Name = "label3"; this label3 Size = new System Drawing Size(212, 18); this label3 TabIndex = 16; this label3 Text = "Chọn đỉnh cần tìm đƣờng đi:"; // // cboTo // this cboTo DropDownStyle = System Windows Forms ComboBoxStyle DropDownList; this cboTo ForeColor = System Drawing Color Red; this cboTo FormattingEnabled = true; this cboTo Location = new System Drawing Point(107, 50); this cboTo Margin = new System Windows Forms Padding(4); this cboTo Name = "cboTo"; this cboTo Size = new System Drawing Size(75, 27); this cboT o TabIndex = 12; // Trang 45 // cboFrom // this cboFrom DropDownStyle = System Windows Forms ComboBoxStyle DropDownList; this cboFrom ForeColor = System Drawing Color Blue; this cboFrom FormattingEnabled = true; this cboFrom Location = new System Drawing Point(11, 50); this cboFrom Margin = new System Windows Forms Padding(4); this cboFrom Name = "cboFrom"; this cboFrom Size = new System Drawing Size(75, 27); this cboFrom TabIndex = 12; // // label2 // this label2 AutoSize = true; this label2 ForeColor = System Drawing Color Red; this label2 Location = new System Drawing Point(109, 32); this label2 Margin = new System Windows Forms Padding(4, 0, 4, 0); this label2 Name = "label2"; this label2 Size = new System Drawing Size(73, 1 9); this label2 TabIndex = 7; this label2 Text = "Đến đỉnh"; // // label1 // this label1 AutoSize = true; Trang 46 this label1 ForeColor = System Drawing Color Blue; t his label1 Location = new System Drawing Point(9, 32); this label1 Margin = new System Windows Forms Padding(4, 0, 4, 0); this label1 Name = "label1"; this label1 Size = new System Drawing Size(65, 19); this label1 TabIndex = 7; this label1 Text = "Từ đỉnh"; // // linkLabel1 // this linkLabel1 AutoSize = true; this linkLabel1 Font = new System Drawing Font("Tahoma", 9 75 F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); this linkLabel1 Location = new System Drawing Point(11, 424); this linkLabel1 Name = "linkLabel1"; this linkLabel1 Size = new System D rawing Size(159, 16); this linkLabel1 TabIndex = 13; this linkLabel1 TabStop = true; this linkLabel1 Text = "Thực hiện: - Ung Tấn Biên"; this linkLabel1 LinkClicked += new System Windows Forms LinkLabelLinkClickedEventHandler(this lin kLabel1_LinkClicked); // // cmdXoaDuongDi // Trang 47 this cmdXoaDuongDi ForeColor = System Drawing Color Blue; this cmdXoaDuongDi Image = ((System Drawing Image)(resources GetObject("cmdXoaDuongDi Ima ge"))); this cmdXoaDuongDi ImageAlign = System Drawing ContentAlignment MiddleLeft; this cmdXoaDuongDi Location = new System Drawing Point(4, 234); this cmdXoaDuongDi Margin = new System Windows Forms Padding(4); this cmdXoaDuongDi Name = "cmdXoaDuongDi"; this cmdXoaDuongDi Size = new System Drawing Size(112, 44); this cmdXoaDuongDi TabIndex = 11; this cmdXoaDuongDi Text = "Xóa cạnh"; this cmdXoaDuongDi TextAlign = System Drawing ContentAlignment MiddleRight; this cmdXoaDuongDi UseVisualStyleBackColor = true; this cmdXoaDuongDi Click += new System EventHandler(this cmdXoaDuongDi_Click); // // cmdXoaDuongDiCuoi // this cmdXoaDuongDiCuoi ForeColor = System Drawing Color Blue; this cmdXoaDuongDiCuoi Image = ((System Drawing Image)(resources GetObject("cmdXoaDuongDiCuoi Image"))); this cmdXoaDuongDiCuoi ImageAlign = System Drawing ContentAlignment MiddleLeft; this cmdXoaDuongDiCuoi Location = new System Drawing Point(16, 187); Trang 48 this cmdXoaDuongDiCuoi Margin = new System Windows Forms Padding(4); this cmdXoaDuongDiCuoi Name = "cmdXoaDuongDiCuoi"; this cmdXoaDuongDiCuoi Size = new System Drawing Size(196, 42); this cmdXoaDuongDiCuoi Ta bIndex = 10; this cmdXoaDuongDiCuoi Text = "Xóa cạnh sau cùng"; this cmdXoaDuongDiCuoi TextAlign = System Drawing ContentAlignment MiddleRight; this cmdXoaDuongDiCuoi UseVisualStyleBackColor = true; this cmdX oaDuongDiCuoi Click += new System EventHandler(this cmdXoaDuongDiCuoi_Click); // // groupBox1 // this groupBox1 Controls Add(this cmdDoiMau); this groupBox1 Controls Add(this cmdXoaDinh); this groupBox1 Enabled = false; this groupBox1 Font = new System Drawing Font("Tahoma", 12F, System Drawing FontStyle Bold, System Drawing GraphicsUnit Point, ((byte)(0))); this groupBox1 ForeColor = System Drawing Color Red; this groupBox1 Location = new System Drawing Point(14, 302); this groupBox1 Margin = new System Windows Forms Padding(4); this groupBox1 Name = "groupBox1"; this groupBox1 Padding = new System Windows Forms Padding(4); Trang 49 this groupBox1 Size = new System Drawing Size(190, 117); this groupBox1 TabIndex = 9; this groupBox1 TabStop = false; this groupBox1 T ext = "Tùy chọn cho đỉnh:"; // // cmdDoiMau // this cmdDoiMau Font = new System Drawing Font("Tahoma", 12F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); thi s cmdDoiMau ForeColor = System Drawing Color Blue; this cmdDoiMau Location = new System Drawing Point(43, 72); this cmdDoiMau Margin = new System Windows Forms Padding(4); this cmdDoiMau Name = "cmdDoiMau"; this cmdDoiMau Size = new System Drawing Size(117, 37); this cmdDoiMau TabIndex = 1; this cmdDoiMau Text = "Đổi màu"; this cmdDoiMau UseVisualStyleBackColor = true; this cmdDoiMau Click += new Sys tem EventHandler(this cmdDoiMau_Click); // // cmdXoaDinh // this cmdXoaDinh Font = new System Drawing Font("Tahoma", 12F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); this cmdXoaDinh ForeColor = System Drawing Color Blue; Trang 50 this cmdXoaDinh Location = new System Drawing Point(43, 27); this cmdXoaDinh Margin = new System Windows Forms Padding(4); this cmdXoaDinh Name = "cmdXoaD inh"; this cmdXoaDinh Size = new System Drawing Size(117, 37); this cmdXoaDinh TabIndex = 0; this cmdXoaDinh Text = "Xóa đỉnh"; this cmdXoaDinh UseVisualStyleBackColor = true; this cmdXoaDinh Clic k += new System EventHandler(this cmdXoaDinh_Click); // // groupBox2 // this groupBox2 Anchor = ((System Windows Forms AnchorStyles)(((System Windows Forms An chorStyles Bottom | System Windows Forms AnchorStyles Left) | System Windows Forms AnchorStyles Right))); this groupBox2 C ontrols Add(this toolStrip1); this groupBox2 Font = new System Drawing Font("Tahoma", 12F, System Drawing FontStyle Bold, System Drawing GraphicsUnit Point, ((byte)(0))); this groupBox2 ForeColor = System Drawing Color Red; this groupBox2 Location = new System Drawing Point(251, 468); this groupBox2 Margin = new System Windows Forms Padding(4); this groupBox2 Name = "groupBox2"; this groupBox2 Padding = new System Windows Forms Padding( 4); Trang 51 this groupBox2 Size = new System Drawing Size(453, 64); this groupBox2 TabIndex = 9; this groupBox2 TabStop = false; this groupBox2 Text = "Công cụ:"; // // toolStrip1 // this toolStrip1 Font = new System Drawing Font("Tahoma", 12F, System Drawing FontStyle Regular, System Drawing GraphicsUnit Point, ((byte)(0))); this toolStrip1 GripStyle = System Windows Forms ToolStripGripStyle Hid den; this toolStrip1 Items AddRange(new System Windows Forms ToolStripItem[] { this cmdDiChuyen, this cmdVeDinh, this cmdVeCanh, this cmdXoa}); this toolStrip1 Location = new System Drawing Point(4, 24); this toolStrip1 Name = "toolStrip1"; this toolStrip1 Padding = new System Windows Forms Padding(0, 0, 2, 0); this toolStrip1 RenderMode = System Win dows Forms ToolStripRenderMode System; this toolStrip1 Size = new System Drawing Size(445, 26); this toolStrip1 Stretch = true; this toolStrip1 TabIndex = 0; // // cmdDiChuyen // Trang 52 this cmdDiChuyen ForeColor = System Drawing Color Blue; this cmdDiChuyen Image = ((System Drawing Image)(resources GetObject("cmdDiChuyen Image "))); this cmdDiChuyen ImageTransparentColor = System Drawing Color Magenta; this cmdDiChuyen Name = "cmdDiChuyen"; this cmdDiChuyen Size = new System Drawing Size(99, 23); this cmdDiChuyen Tag = "0"; this cmdDiChuyen Text = "Di chuyển"; this cmdDiChuyen ToolTipText = "Di chu yển đối tƣợng đƣợc chọn từ chỗ này sang chỗ khác"; this cmdDiChuyen Click += new System EventHandler(this toolStripButton_Click); // // cmdVeDinh // this cmdVeDinh ForeColor = System Drawing Color Blue; this cmdVeDinh Image = ((System Drawing Image)(resources GetObject("cmdVeDinh Image") )); this cmdVeDinh ImageTransparentColor = System Drawing Color Magenta; this cmdVeDinh Name = "

TỔNG QUAN VỀ LÝ THUYẾT ĐỒ THỊ

CÁC KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ

Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối các đỉnh này Chúng ta phân biệt các loại đồ thị khác nhau bởi kiểu và số lƣợng cạnh nối hai đỉnh nào đó của đồ thị Để có thể hình dung đƣợc tại sao lại cần đến các loại đồ thị khác nhau, chúng ta sẽ nêu ví dụ sử dụng chúng để mô tả một mạng máy tính Giả sử ta có một mạng gồm các máy tính và các kênh điện thoại nối các máy tính này Chúng ta có thể biểu diễn các vị trí đặt máy tính bởi các điểm và các kênh thoại nối chúng bởi các đoạn nối

Hình 1 Sơ đồ mạng máy tính

Nhận thấy rằng trong sơ đồ mạng máy tính ở hình 1, giữa hai máy tính bất kỳ chỉ cho phép nhiều nhất là một kênh thoại nối chúng, kênh thoại này cho phép liên lạc cả hai chiều và không có máy tính nào lại đƣợc nối với chính nó Sơ đồ mạng máy tính cho trong hình 1 đƣợc gọi là đơn đồ thị vô hướng từ đó ta đi đến một định nghĩa sau: Định nghĩa 1 Đơn đồ thị vô hướng G=(V,E) bao gồm V là tập đỉnh, và E là tập các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh

Trong trường hợp giữa hai máy tính nào đó thường xuyên phải truyền tải nhiều thông tin buộc lòng người ta phải nối hai máy này bởi nhiều kênh thoại Lúc này ta có mô hình mạng máy tính mới đƣợc sinh ra nhƣ sau:

Hình 2 Sơ đồ mạng máy tính với đa kênh thoại

Từ đó chúng ta có thêm một định nghĩa tiếp theo nhƣ sau: Định nghĩa 2 Đa đồ thị vô hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh Hai cạnh e 1 va e 2 được gọi là cạnh lặp nếu chúng cùng tương ứng với một cặp đỉnh

Hình 3 Sơ đồ mạng máy tính với kênh thông báo

Rõ ràng mỗi đơn đồ thị đều là đa đồ thị, nhƣng không phải đa đồ thị nào cũng là đơn đồ thị, vì trong đa đồ thị có hai hay nhiều hơn cạnh nối một cặp đỉnh nào đó Trong mạng máy tính có thể có những kênh thoại nối một máy tính nào đó với chính nó (chẳng hạn với mục đích thông báo) Mạng nhƣ vậy đƣợc cho trong hình 3 Nhƣ vậy đa đồ thị không thể mô tả đƣợc mạng nhƣ vậy, bởi vì có những khuyên (cạnh nối một đỉnh vói chính nó) Trong trường hợp này chúng ta cần sử dụng đến khái niệm giả đồ thị vô hướng, được định nghĩa như sau: Định nghĩa 3 Giả đồ thị vô hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp không có thứ tự gồm hai phần tử (không nhất thiết phải khác nhau) của V gọi là các cạnh Cạnh e được gọi là khuyên nếu có dạng e=(u,u)

Các kênh thoại trong mạng máy tính có thể chỉ cho phép truyền tin theo một chiều Chẳng hạn trong hình 4 máy chủ ở Hà Nội chỉ có thể nhận tin từ các máy ở địa phương, có một số máy chỉ có thể gửi tin đi, còn các kênh thoại cho phép truyền tin theo cả hai chiều được thay thế bởi hai cạnh có hướng ngược chiều nhau

Hình 4 Mạng máy tính với các kênh thoại một chiều

Ta đi đến định nghĩa sau: Định nghĩa 4 Đơn đồ thị có hướng G=(V,E) bao gồm V là tập các đỉnh và E là tập các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung

Nếu trong mạng có thể có đa kênh thoại một chiều, ta sẽ phải sử dụng đến khái niệm đa đồ thị có hướng: Định nghĩa 5 Đa đồ thị có hướng G=(V,E) bao gồm V là tập các đỉnh, và E là họ các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung Hai cung e 1 va e 2 tương ứng với cùng một cặp đỉnh được gọi là cung lặp

1.1.2 Định nghĩa đường đi, chu trình, đồ thị liên thông Định nghĩa 1 Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số nguyên dương, trên đồ thị vô hướng G=(V,E) là dãy x o , x 1 , , x n-1 , x n trong đó u=x 0 , v=x n , ( x i , x i+1 ) E , i= 0, 1, 2 , , n-1 Đường đi nói trên còn có thể biểu diễn dưới dạng các cạnh:

(x 0 , x 1 ) , ( x 1 , x 2 ), , ( x n-1 , x n ) Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi Đường đi có đỉnh đầu trùng với đỉnh cuối (tức là u=v) được gọi là chu trình Đường đi hay chu trình được gọi là đơn nếu như không có cạnh nào bị lặp lại

Ví dụ 1 Trên đồ thị vô hướng cho trong hình 1: a,d,c,f,e là đường đi đơn độ dài

4 Còn d,e,c,a không là đường đi do (e,c) không phải là cạnh của đồ thị Dãy b,c,f,e,b là chu trình độ dài 4 Đường đi a,b,e,d,a,b có độ dài là 5 không phải là đường đi đơn, do cạnh (a,b) có mặt trong nó hai lần

Hình 5 Đường đi trên đồ thị

Khái niệm đường đi và chu trình trên đồ thị có hướng được định nghĩa hoàn toàn tương tự như trường hợp đồ thị vô hướng, chỉ khác là ta chú ý đến hướng trên các cung Định nghĩa 2 Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số nguyên dương, trên đồ thị có hướng G=(V,A) là dãy x o , x 1 , , x n-1 , x n trong đó u=x 0 , v=x n , ( x i , x i+1 )  A , i= 0, 1, 2 , , n-1 Đường đi nói trên còn có thể biểu diễn dưới dạng các cung:

(x 0 , x 1 ) , ( x 1 , x 2 ), , ( x n-1 , x n ) Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi Đường đi có đỉnh đầu trùng với đỉnh cuối (tức là u=v) được gọi là chu trình Đường đi hay chu trình được gọi là đơn nếu như không có cung nào bị lặp lại

Ví dụ 2 Trên đồ thị có hướng cho trong hình 1: a,d,c,f,e là đường đi đơn độ dài

4 Còn d,e,c,a không là đường đi do (e,c) không phải là cung của đồ thị Dãy b,c,f,e,b là chu trình độ dài 4 Đường đi a,b,e,d,a,b có độ dài là 5 không phải là đường đi đơn, do cung (a,b) có mặt trong nó hai lần

Xét một mạng máy tính Một câu hỏi đặt ra là hai máy tính bất kỳ trong mạng này có thể trao đổi đƣợc thông tin với nhau hoặc trực tiếp qua kênh nối chúng hợăc thông qua một hoặc vài máy tính trung gian trong mạng? Nếu sử dụng đồ thị để biểu diễn mạng máy tính này (trong đó các đỉnh của đồ thị tương ứng với các máy tính, còn các cạnh tương ứng với các kênh nối) câu hỏi đó được phát biểu trong ngôn ngữ đồ thị như sau: Tồn tại hay chăng đường đi giữa mọi cặp đỉnh của đồ thị ? Định nghĩa 3 Đồ thị vô hướng G=(V,E) được gọi là liên thông nếu luôn tìm được đường đi giữa hai đỉnh bất kỳ của nó

CÁC KHÁI NIỆM VỀ ĐƯỜNG ĐI NGẮN NHẤT

Trong phần này chúng ta chỉ xét đồ thị có hướng G=(V,E) và |V|=n,|E|=m với các cung được gán trọng số, nghĩa là, mỗi cung (u,v)E của nó được đặt tương ứng với một số thực a(u,v) gọi là trọng số của nó Chúng ta sẽ đặt a(u,v)=, nếu (u,v)E Nếu dãy v 0 , v1 , , vp là một đường đi trên G, thì độ dài của nó được định nghĩa là tổng sau: tức là, độ dài của đường đi chính là tổngcác trọng số trên các cung của nó (Chú ý rằng nếu chúng ta gán trọng số cho tất cả các cung đều bằng 1, thì ta thu đƣợc định nghĩa độ dài đuờng đi như là số cung của đường đi

Bài toán tìm đường đi ngắn nhất trên đồ thị dưới dạng tổng quát có thể được phát biểu dưới dạng tổng quát như sau: Tìm đường đi có độ dài nhỏ nhất từ một đỉnh xuất phát sV đến đỉnh cuối (đích) tV Đường đi như vậy sẽ gọi là đường đi ngắn nhất từ s đến t còn độ dài của nó sẽ kí hiệu là d(s,t) và còn gọi là khoảng cách từ s đến t (khoảng cách định nghĩa như vậy có thể là số âm) Nếu như không tồn tại đường đi từ s đến t thì ta đặt d(s,t)= từ đó ta thấy chu trình trong đồ thị có độ dài dương, thì trong đường đi ngắn nhất không có đỉnh nào lặp lại (đường đi như thế gọi là đường đi cơ bản )

Mặt khác, nếu trong đồ thị có chu trình với độ dài âm (gọi là chu trình âm ) thì khoảng cách giữa 1 số cặp đỉnh nào đó của đồ thị có thể là không xác định, bởi vì, bằng cách đi vòng theo chu trình này một số đủ lớn lần, ta có thể chỉ ra đường đi giữa các đỉnh này có độ dài nhỏ hơn bất kì số thực cho trước nào Trong truờng hợp như vậy, có thể đặt vấn đề tìm đường đi cơ bản ngắn nhất, tuy nhiên bài toán đặt ra sẽ trở nên phức tạp hơn rất nhiều, bởi vì nó chứa bài toán xét sự tồn tại đường đi Hamilton trong đồ thị như là một trường hợp riêng

Trước hết cần chú ý rằng nếu biết khoảng cách từ s đến t, thì đường đi ngắn nhất từ s đến t, trong trường hợp trọng số không âm, có thể tìm một cách dễ dàng Để tìm đường đi, chỉ cần chú ý là đối với cặp đỉnh s,tV tuỳ ý (st) luôn tìm được đỉnh v sao cho: d(s,t) = d(s,v) + a(v,t)

Thật vậy đỉnh v như vậy chính là đỉnh đi trước đỉnh t trong đường đi ngắn nhất từ s đến t Tiếp theo ta có thể tìm đƣợc u sao cho d(s,v)=d(s,u)+a(u,v), Từ giả thiết về tính không âm của các trọng số dễ dàng suy ra rằng dãy t,v,u không chứa đỉnh lặp lại và kết thúc ở đỉnh s Rõ ràng dãy thu được xác định đường đi ngắn nhất từ s đến t

1.2.2 Đường đi ngắn nhất xuất phát từ một đỉnh

Phần lớn các thuật toán tìm khoảng cách giữa hai đỉnh s và t đƣợc xây dựng nhờ kỹ thuật tính toán mà ta có thể mô tả nhƣ sau: từ ma trận trọng số a[u,v],u,vV, ta tính cận trên d[v] của khoảng cách từ s đến tất cả các đỉnh vV Mỗi khi phát hiện d[u]+a[u,v] 0)

//Sự kiện nhấn chuột protected override void OnMouseDown(MouseEventArgs e)

} protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e);

} protected override void OnPaint(PaintEventArgs e) {

// base.OnPaint(e); string text = DisplayName.ToString(); e.Graphics.SmoothingMode SmoothingMode.AntiAlias;

Rectangle rect = this.ClientRectangle; rect.Inflate(-1, -1); if (_isCreating || _isRevoming)

Color.Red); e.Graphics.FillEllipse(new SolidBrush(c), rect);

Pen p = new Pen(this.ForeColor); if (this.Selected)

SizeF s = e.Graphics.MeasureString(text, this.Font); e.Graphics.DrawString(text, this.Font, foreBrush, (this.Width - s.Width) / 2, (this.Height - s.Height) / 2);

GraphicsPath path = new GraphicsPath(); path.AddEllipse(rect); this.Region = new System.Drawing.Region(path); } public override string ToString()

3.2.2 Xây dựng lớp thƣ viện Matrix:

Xây dựng lớp thƣ viện Matrix.cs để vẽ lên ma trận của đồ thị Đồng thời, cài đặt thuật toán Floyd vào trong lớp này để sử dụng tìm đường đi ngắn nhất giữa mọi cặp đỉnh của đồ thị

{ const int OFFSET = 20; const int HANDLE_SIZE = 6;//Mặc định nên để là 6

Point _pRightBottom; int[,] _data; public FloydCell[,] FloydData; float _size;

Rectangle _rectHandle1, _rectHandle2, _rectHandle3, _rectHandle4; int _handleIndex = -1; bool _selected = false; bool _resizing = false; public Matrix()

_rectHandle1 = new Rectangle(0, 0, HANDLE_SIZE, HANDLE_SIZE); this.MinimumSize = new Size(20, 20);//Mặc định là 20x20 this.Size = new Size(160, 160);//Mặc định mình nên gán nó 160x160 this.DoubleBuffered = true;

//Áp dụng theo giáo trình mà cô An gửi public void Floyd()

{ if (Data == null) return; int n = Data.GetLength(0);

FloydData = new FloydCell[n, n]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)

{ if (FloydData[j, k].Value < 0 || FloydData[j, i].Value + FloydData[i, k].Value

FloydData[j, k].Value = FloydData[j, i].Value + FloydData[i, k].Value;

} protected override void OnMouseHover(EventArgs e)

} protected override void OnMouseLeave(EventArgs e)

} protected override void OnMouseDown(MouseEventArgs e)

_pRightBottom = new Point(this.Right, this.Bottom);

// Kiểm tra cursor có nằm trên handle nào không > if (_rectHandle1.IntersectsWith(cursor)) _handleIndex = 0; else if

(_rectHandle2.IntersectsWith(cursor)) _handleIndex = 1; else if

(_rectHandle3.IntersectsWith(cursor)) _handleIndex = 2; else if

(_rectHandle4.IntersectsWith(cursor)) _handleIndex = 3; else

} protected override void OnMouseMove(MouseEventArgs e)

// Thay đổi vị trí và kích thướt đưa vào handle đƣợc dùng if (_handleIndex == 0)

{ this.Cursor = Cursors.SizeNWSE; this.Location this.Parent.PointToClient(this.PointToScreen(e.Location)); this.Width = _pRightBottom.X - this.Left; this.Height = _pRightBottom.Y - this.Top;

{ this.Cursor = Cursors.SizeNESW; this.Width = e.X; this.Top this.Parent.PointToClient(this.PointToScreen(e.Location)).Y; this.Height = _pRightBottom.Y - this.Top;

{ this.Cursor = Cursors.SizeNWSE; this.Width = e.X; this.Height = e.Y;

{ this.Cursor = Cursors.SizeNESW; this.Left this.Parent.PointToClient(this.PointToScreen(e.Location)).X; this.Width = _pRightBottom.X - this.Left; this.Height = e.Y;

Point p this.Parent.PointToClient(this.PointToScreen(e.Location)); p.X -= _p.X; p.Y -= _p.Y; this.Location = p;

} protected override void OnMouseUp(MouseEventArgs e)

{ this.Cursor = Cursors.Arrow; base.OnMouseUp(e);

} protected override void OnSizeChanged(EventArgs e)

} protected override void OnResize(EventArgs e)

Data.GetLength(0); this.Height = this.Width;

_rectHandle2 = new Rectangle(this.Width -

HANDLE_SIZE - 1, 0, HANDLE_SIZE, HANDLE_SIZE);

_rectHandle3 = new Rectangle(this.Width -

HANDLE_SIZE - 1, this.Height - HANDLE_SIZE - 1, HANDLE_SIZE, HANDLE_SIZE);

_rectHandle4 = new Rectangle(0, this.Height - HANDLE_SIZE - 1, HANDLE_SIZE, HANDLE_SIZE);

} protected override void OnPaint(PaintEventArgs e)

DrawMatrix(Data, e.Graphics); if (_selected)

// vẽ handles e.Graphics.FillRectangle(Brushes.White, _rectHandle1); e.Graphics.FillRectangle(Brushes.White, _rectHandle2); e.Graphics.FillRectangle(Brushes.White, _rectHandle3); e.Graphics.FillRectangle(Brushes.White, _rectHandle4); e.Graphics.DrawRectangle(Pens.Gray,

_rectHandle1); e.Graphics.DrawRectangle(Pens.Gray,

_rectHandle2); e.Graphics.DrawRectangle(Pens.Gray,

_rectHandle3); e.Graphics.DrawRectangle(Pens.Gray,

} e.Graphics.DrawRectangle(Pens.Black, 0, 0, this.Width - 1, this.Height - 1); base.OnPaint(e);

} void DrawMatrix(int[,] array, Graphics g)

{ int n = array.GetLength(0); for (int i = 0; i < n; i++)

{ float x = i * _size + OFFSET; string s = ((char)(i + 'A')).ToString(); g.DrawString(s, this.Font, Brushes.Blue, new PointF(0, x)); g.DrawString(s, this.Font, Brushes.Blue, new PointF(x, 0)); g.DrawLine(Pens.Gray, x, 0, x, this.Height); g.DrawLine(Pens.Gray, 0, x, this.Width, x); for (int j = 0; j < n; j++)

{ v FloydData[i,j].Value.ToString(); g.FillRectangle(Brushes.LightGray, new RectangleF(x + 1, j * _size + OFFSET + 1, _size - 1, _size - 1)); g.DrawString(v, this.Font, Brushes.Red, new PointF(x, j * _size + OFFSET)); continue;

} else v = array[i, j].ToString(); g.DrawString(v, this.Font,

Brushes.DarkMagenta, new PointF(x, j * _size + OFFSET));

{ public int Previous; public int Value; public FloydCell(int value)

{ } public FloydCell(int previous, int value)

{ this.Previous = previous; this.Value = value;

Xây dựng lớp Edge.cs nhằm hỗ trợ việc vẽ cạnh của đồ thị

[Serializable] class EdgeCollection : IEnumerable

List _list; public int SelectedIndex

} public bool Add(Edge edge)

Edge newEdge = new Edge(edge.End, edge.Start); if (_list.Contains(newEdge))

{ edge = _list[_list.IndexOf(newEdge)]; edge.IsUndirected = true;

} public bool Contains(Edge edge)

} public Edge this[int index]

} public bool Contains(Edge edge, bool checkInverted) { if (_list.Contains(edge)) return true; if (checkInverted) return _list.Contains(new Edge(edge.End, edge.Start)); return false;

} public void RemoveAt(int index)

{ private const float EPSILON = 2f; public int Start; public int End; public bool IsUndirected; public bool IsRemoving; public Edge(int start, int end)

{ this.Start = start; this.End = end; this.IsUndirected = false;

} public static bool Contains(PointF start, PointF end, PointF p)

{ if (p.X < Math.Min(start.X, end.X) || p.X > Math.Max(start.X, end.X) || p.Y < Math.Min(start.Y, end.Y) || p.Y > Math.Max(start.Y, end.Y)) return false; var dx = end.X - start.X; var dy = end.Y - start.Y; var v1 = new Vector2D(dx, dy).Length; float cx = p.X - start.X; float cy = p.Y - start.Y; var v2 = new Vector2D(cx, cy).Length; var v3 = new Vector2D(p.X - end.X, p.Y - end.Y).Length; var pp = (v1 + v2 + v3) / 2; var s = Math.Sqrt(pp * (pp - v1) * (pp - v2) * (pp - v3)); var h = s * 2 / v1;

} public override bool Equals(Object obj)

{ if (!(obj is Edge)) return false;

Edge con = (Edge)obj; if (this.Start == con.Start && this.End = con.End) return true; if (this.IsUndirected && this.Start == con.End

&& this.End == con.Start) return true; return false;

Xây dựng form giao diện của chương trình

Xây dựng form gồm các điều khiển:

ComboBox cboFrom: Lựa chọn đỉnh bắt đầu

ComboBox cboTo: Lựa chọn đỉnh đích

Button cmduongDi: Tìm đường đi ngắn nhất từ đỉnh bắt đầu đến đỉnh đích và các điều khiển liên quan khác

Mã nguồn: private void InitializeComponent()

// this.cmdDuongDi.ForeColor System.Drawing.Color.Blue; this.cmdDuongDi.Image ((System.Drawing.Image)(resources.GetObject("cmdDuongDi.Image"))); this.cmdDuongDi.ImageAlign System.Drawing.ContentAlignment.MiddleLeft; this.cmdDuongDi.Location = new

System.Drawing.Point(16, 144); this.cmdDuongDi.Margin = new

System.Windows.Forms.Padding(4); this.cmdDuongDi.Name = "cmdDuongDi"; this.cmdDuongDi.Size = new

System.Drawing.Size(196, 42); this.cmdDuongDi.TabIndex = 3; this.cmdDuongDi.Text = "Đường đi ngắn nhất"; this.cmdDuongDi.TextAlign System.Drawing.ContentAlignment.MiddleRight; this.cmdDuongDi.UseVisualStyleBackColor = true; this.cmdDuongDi.Click += new

System.EventHandler(this.cmdDuongDi_Click);

// this.cmdXoaHet.ForeColor System.Drawing.Color.Blue; this.cmdXoaHet.Image ((System.Drawing.Image)(resources.GetObject("cmdXoaHet.Image") )); this.cmdXoaHet.ImageAlign System.Drawing.ContentAlignment.MiddleLeft; this.cmdXoaHet.Location = new

System.Drawing.Point(119, 236); this.cmdXoaHet.Margin = new

System.Windows.Forms.Padding(4); this.cmdXoaHet.Name = "cmdXoaHet"; this.cmdXoaHet.Size = new

System.Drawing.Size(112, 42); this.cmdXoaHet.TabIndex = 4; this.cmdXoaHet.Text = "Xóa tất cả"; this.cmdXoaHet.TextAlign System.Drawing.ContentAlignment.MiddleRight; this.cmdXoaHet.UseVisualStyleBackColor = true; this.cmdXoaHet.Click += new

System.EventHandler(this.cmdXoaHet_Click);

// this.panel1.Anchor ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.An chorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) |

System.Windows.Forms.AnchorStyles.Left))); this.panel1.BorderStyle System.Windows.Forms.BorderStyle.Fixed3D; this.panel1.Controls.Add(this.linkLabel3); this.panel1.Controls.Add(this.linkLabel2); this.panel1.Controls.Add(this.panel2); this.panel1.Controls.Add(this.linkLabel1); this.panel1.Controls.Add(this.cmdXoaDuongDi); this.panel1.Controls.Add(this.cmdXoaDuongDiCuoi); this.panel1.Controls.Add(this.groupBox1); this.panel1.Controls.Add(this.cmdDuongDi); this.panel1.Controls.Add(this.cmdXoaHet); this.panel1.Location = new

System.Drawing.Point(3, 41); this.panel1.Margin = new

System.Windows.Forms.Padding(4); this.panel1.Name = "panel1"; this.panel1.Size = new System.Drawing.Size(240, 491); this.panel1.TabIndex = 7;

// this.linkLabel3.AutoSize = true; this.linkLabel3.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.linkLabel3.Location = new

System.Drawing.Point(77, 443); this.linkLabel3.Name = "linkLabel3"; this.linkLabel3.Size = new

System.Drawing.Size(126, 16); this.linkLabel3.TabIndex = 18; this.linkLabel3.TabStop = true; this.linkLabel3.Text = "- Nguyễn Đức Chung"; this.linkLabel3.LinkClicked += new

System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lin kLabel3_LinkClicked);

// this.linkLabel2.AutoSize = true; this.linkLabel2.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.linkLabel2.Location = new

System.Drawing.Point(5, 467); this.linkLabel2.Name = "linkLabel2"; this.linkLabel2.Size = new

System.Drawing.Size(229, 16); this.linkLabel2.TabIndex = 17; this.linkLabel2.TabStop = true; this.linkLabel2.Text = "GV hướng dẫn: ThS Lê Thị Nguyên An"; this.linkLabel2.LinkClicked += new

System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lin kLabel2_LinkClicked);

// this.panel2.BorderStyle System.Windows.Forms.BorderStyle.FixedSingle; this.panel2.Controls.Add(this.chkVoHuong); this.panel2.Controls.Add(this.label3); this.panel2.Controls.Add(this.cboTo); this.panel2.Controls.Add(this.cboFrom); this.panel2.Controls.Add(this.label2); this.panel2.Controls.Add(this.label1); this.panel2.Location = new

System.Drawing.Point(5, 3); this.panel2.Name = "panel2"; this.panel2.Size = new System.Drawing.Size(219, 122); this.panel2.TabIndex = 16;

System.Drawing.Point(28, 85); this.chkVoHuong.Margin = new

System.Windows.Forms.Padding(4); this.chkVoHuong.Name = "chkVoHuong"; this.chkVoHuong.Size = new

System.Drawing.Size(154, 29); this.chkVoHuong.TabIndex = 17; this.chkVoHuong.Text = "Đồ thị vô hướng"; this.chkVoHuong.UseVisualStyleBackColor = true; this.chkVoHuong.CheckedChanged += new

System.EventHandler(this.chkVoHuong_CheckedChanged);

// this.label3.AutoSize = true; this.label3.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label3.ForeColor System.Drawing.Color.Red; this.label3.Location = new

System.Drawing.Point(5, 6); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(212, 18); this.label3.TabIndex = 16; this.label3.Text = "Chọn đỉnh cần tìm đường đi:";

// this.cboTo.DropDownStyle System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboTo.ForeColor System.Drawing.Color.Red; this.cboTo.FormattingEnabled = true; this.cboTo.Location = new

System.Drawing.Point(107, 50); this.cboTo.Margin = new

System.Windows.Forms.Padding(4); this.cboTo.Name = "cboTo"; this.cboTo.Size = new System.Drawing.Size(75, 27); this.cboTo.TabIndex = 12;

// this.cboFrom.DropDownStyle System.Windows.Forms.ComboBoxStyle.DropDownList; this.cboFrom.ForeColor System.Drawing.Color.Blue; this.cboFrom.FormattingEnabled = true; this.cboFrom.Location = new

System.Drawing.Point(11, 50); this.cboFrom.Margin = new

System.Windows.Forms.Padding(4); this.cboFrom.Name = "cboFrom"; this.cboFrom.Size = new System.Drawing.Size(75, 27); this.cboFrom.TabIndex = 12;

// this.label2.AutoSize = true; this.label2.ForeColor System.Drawing.Color.Red; this.label2.Location = new

System.Drawing.Point(109, 32); this.label2.Margin = new

System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(73, 19); this.label2.TabIndex = 7; this.label2.Text = "Đến đỉnh";

// this.label1.AutoSize = true; this.label1.ForeColor System.Drawing.Color.Blue; this.label1.Location = new

System.Drawing.Point(9, 32); this.label1.Margin = new

System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(65, 19); this.label1.TabIndex = 7; this.label1.Text = "Từ đỉnh";

// this.linkLabel1.AutoSize = true; this.linkLabel1.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.linkLabel1.Location = new

System.Drawing.Point(11, 424); this.linkLabel1.Name = "linkLabel1"; this.linkLabel1.Size = new

System.Drawing.Size(159, 16); this.linkLabel1.TabIndex = 13; this.linkLabel1.TabStop = true; this.linkLabel1.Text = "Thực hiện: - Ung Tấn Biên"; this.linkLabel1.LinkClicked += new

System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lin kLabel1_LinkClicked);

// this.cmdXoaDuongDi.ForeColor System.Drawing.Color.Blue; this.cmdXoaDuongDi.Image ((System.Drawing.Image)(resources.GetObject("cmdXoaDuongDi.Ima ge"))); this.cmdXoaDuongDi.ImageAlign System.Drawing.ContentAlignment.MiddleLeft; this.cmdXoaDuongDi.Location = new

System.Drawing.Point(4, 234); this.cmdXoaDuongDi.Margin = new

System.Windows.Forms.Padding(4); this.cmdXoaDuongDi.Name = "cmdXoaDuongDi"; this.cmdXoaDuongDi.Size = new

System.Drawing.Size(112, 44); this.cmdXoaDuongDi.TabIndex = 11; this.cmdXoaDuongDi.Text = "Xóa cạnh"; this.cmdXoaDuongDi.TextAlign System.Drawing.ContentAlignment.MiddleRight; this.cmdXoaDuongDi.UseVisualStyleBackColor true; this.cmdXoaDuongDi.Click += new

System.EventHandler(this.cmdXoaDuongDi_Click);

// this.cmdXoaDuongDiCuoi.ForeColor System.Drawing.Color.Blue; this.cmdXoaDuongDiCuoi.Image ((System.Drawing.Image)(resources.GetObject("cmdXoaDuongDiCuoi Image"))); this.cmdXoaDuongDiCuoi.ImageAlign System.Drawing.ContentAlignment.MiddleLeft; this.cmdXoaDuongDiCuoi.Location = new

System.Drawing.Point(16, 187); this.cmdXoaDuongDiCuoi.Margin = new

System.Windows.Forms.Padding(4); this.cmdXoaDuongDiCuoi.Name "cmdXoaDuongDiCuoi"; this.cmdXoaDuongDiCuoi.Size = new

System.Drawing.Size(196, 42); this.cmdXoaDuongDiCuoi.TabIndex = 10; this.cmdXoaDuongDiCuoi.Text = "Xóa cạnh sau cùng"; this.cmdXoaDuongDiCuoi.TextAlign System.Drawing.ContentAlignment.MiddleRight; this.cmdXoaDuongDiCuoi.UseVisualStyleBackColor

= true; this.cmdXoaDuongDiCuoi.Click += new

System.EventHandler(this.cmdXoaDuongDiCuoi_Click);

// this.groupBox1.Controls.Add(this.cmdDoiMau); this.groupBox1.Controls.Add(this.cmdXoaDinh); this.groupBox1.Enabled = false; this.groupBox1.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.groupBox1.ForeColor System.Drawing.Color.Red; this.groupBox1.Location = new

System.Drawing.Point(14, 302); this.groupBox1.Margin = new

System.Windows.Forms.Padding(4); this.groupBox1.Name = "groupBox1"; this.groupBox1.Padding = new

System.Windows.Forms.Padding(4); this.groupBox1.Size = new

System.Drawing.Size(190, 117); this.groupBox1.TabIndex = 9; this.groupBox1.TabStop = false; this.groupBox1.Text = "Tùy chọn cho đỉnh:"; //

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.cmdDoiMau.ForeColor System.Drawing.Color.Blue; this.cmdDoiMau.Location = new

System.Drawing.Point(43, 72); this.cmdDoiMau.Margin = new

System.Windows.Forms.Padding(4); this.cmdDoiMau.Name = "cmdDoiMau"; this.cmdDoiMau.Size = new

System.Drawing.Size(117, 37); this.cmdDoiMau.TabIndex = 1; this.cmdDoiMau.Text = "Đổi màu"; this.cmdDoiMau.UseVisualStyleBackColor = true; this.cmdDoiMau.Click += new

System.EventHandler(this.cmdDoiMau_Click);

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.cmdXoaDinh.ForeColor System.Drawing.Color.Blue; this.cmdXoaDinh.Location = new

System.Drawing.Point(43, 27); this.cmdXoaDinh.Margin = new

System.Windows.Forms.Padding(4); this.cmdXoaDinh.Name = "cmdXoaDinh"; this.cmdXoaDinh.Size = new

System.Drawing.Size(117, 37); this.cmdXoaDinh.TabIndex = 0; this.cmdXoaDinh.Text = "Xóa đỉnh"; this.cmdXoaDinh.UseVisualStyleBackColor = true; this.cmdXoaDinh.Click += new

System.EventHandler(this.cmdXoaDinh_Click);

// this.groupBox2.Anchor ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.An chorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) |

System.Windows.Forms.AnchorStyles.Right))); this.groupBox2.Controls.Add(this.toolStrip1); this.groupBox2.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.groupBox2.ForeColor System.Drawing.Color.Red; this.groupBox2.Location = new

System.Drawing.Point(251, 468); this.groupBox2.Margin = new

System.Windows.Forms.Padding(4); this.groupBox2.Name = "groupBox2"; this.groupBox2.Padding = new

System.Windows.Forms.Padding(4); this.groupBox2.Size = new

System.Drawing.Size(453, 64); this.groupBox2.TabIndex = 9; this.groupBox2.TabStop = false; this.groupBox2.Text = "Công cụ:";

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.toolStrip1.GripStyle System.Windows.Forms.ToolStripGripStyle.Hidden; this.toolStrip1.Items.AddRange(new

System.Windows.Forms.ToolStripItem[] { this.cmdDiChuyen, this.cmdVeDinh, this.cmdVeCanh, this.cmdXoa}); this.toolStrip1.Location = new

System.Drawing.Point(4, 24); this.toolStrip1.Name = "toolStrip1"; this.toolStrip1.Padding = new

System.Windows.Forms.Padding(0, 0, 2, 0); this.toolStrip1.RenderMode System.Windows.Forms.ToolStripRenderMode.System; this.toolStrip1.Size = new

System.Drawing.Size(445, 26); this.toolStrip1.Stretch = true; this.toolStrip1.TabIndex = 0;

// this.cmdDiChuyen.ForeColor System.Drawing.Color.Blue; this.cmdDiChuyen.Image ((System.Drawing.Image)(resources.GetObject("cmdDiChuyen.Image

"))); this.cmdDiChuyen.ImageTransparentColor System.Drawing.Color.Magenta; this.cmdDiChuyen.Name = "cmdDiChuyen"; this.cmdDiChuyen.Size = new

System.Drawing.Size(99, 23); this.cmdDiChuyen.Tag = "0"; this.cmdDiChuyen.Text = "Di chuyển"; this.cmdDiChuyen.ToolTipText = "Di chuyển đối tƣợng đƣợc chọn từ chỗ này sang chỗ khác"; this.cmdDiChuyen.Click += new

System.EventHandler(this.toolStripButton_Click);

// this.cmdVeDinh.ForeColor System.Drawing.Color.Blue; this.cmdVeDinh.Image ((System.Drawing.Image)(resources.GetObject("cmdVeDinh.Image") )); this.cmdVeDinh.ImageTransparentColor System.Drawing.Color.Magenta; this.cmdVeDinh.Name = "cmdVeDinh"; this.cmdVeDinh.Size = new

System.Drawing.Size(83, 23); this.cmdVeDinh.Tag = "1"; this.cmdVeDinh.Text = "Vẽ đỉnh"; this.cmdVeDinh.ToolTipText = "Vẽ đỉnh của đồ thị bằng cách nhấp chuột"; this.cmdVeDinh.Click += new

System.EventHandler(this.toolStripButton_Click);

// this.cmdVeCanh.ForeColor System.Drawing.Color.Blue; this.cmdVeCanh.Image ((System.Drawing.Image)(resources.GetObject("cmdVeCanh.Image") )); this.cmdVeCanh.ImageTransparentColor System.Drawing.Color.Magenta; this.cmdVeCanh.Name = "cmdVeCanh"; this.cmdVeCanh.Size = new

System.Drawing.Size(85, 23); this.cmdVeCanh.Tag = "2"; this.cmdVeCanh.Text = "Vẽ cạnh"; this.cmdVeCanh.ToolTipText = "Vẽ cạnh của đồ thị bằng cách kéo thả"; this.cmdVeCanh.Click += new

System.EventHandler(this.toolStripButton_Click);

// this.cmdXoa.ForeColor System.Drawing.Color.Blue; this.cmdXoa.Image ((System.Drawing.Image)(resources.GetObject("cmdXoa.Image"))); this.cmdXoa.ImageTransparentColor System.Drawing.Color.Magenta; this.cmdXoa.Name = "cmdXoa"; this.cmdXoa.Size = new System.Drawing.Size(55, 23); this.cmdXoa.Tag = "3"; this.cmdXoa.Text = "Xóa"; this.cmdXoa.ToolTipText = "Xóa đối tƣợng đƣợc chọn";

// this.cmdThoat.DialogResult System.Windows.Forms.DialogResult.Cancel; this.cmdThoat.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.cmdThoat.ForeColor System.Drawing.Color.Red; this.cmdThoat.Image ((System.Drawing.Image)(resources.GetObject("cmdThoat.Image")) ); this.cmdThoat.ImageAlign System.Drawing.ContentAlignment.MiddleLeft; this.cmdThoat.Location = new

System.Drawing.Point(702, 485); this.cmdThoat.Name = "cmdThoat"; this.cmdThoat.Size = new

System.Drawing.Size(99, 40); this.cmdThoat.TabIndex = 10; this.cmdThoat.Text = "Thoát"; this.cmdThoat.TextAlign System.Drawing.ContentAlignment.MiddleRight; this.cmdThoat.UseVisualStyleBackColor = true; this.cmdThoat.Click += new

System.EventHandler(this.cmdThoat_Click);

// this.label4.AutoSize = true; this.label4.Font = new

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.label4.ForeColor System.Drawing.Color.Blue; this.label4.Location = new

System.Drawing.Point(179, 9); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(474, 25); this.label4.TabIndex = 11; this.label4.Text = "CHƯƠNG TRÌNH DEMO THUẬT TOÁN FLOYD"; this.label4.TextAlign System.Drawing.ContentAlignment.MiddleCenter;

// this.BangVe.Anchor ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.A nchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) |

System.Windows.Forms.AnchorStyles.Left)

System.Windows.Forms.AnchorStyles.Right))); this.BangVe.BackColor System.Drawing.Color.White; this.BangVe.IsUndirectedGraph = false; this.BangVe.Location = new

System.Drawing.Point(252, 41); this.BangVe.Margin = new

System.Windows.Forms.Padding(4); this.BangVe.Name = "BangVe"; this.BangVe.Size = new System.Drawing.Size(558, 418); this.BangVe.TabIndex = 0; this.BangVe.ContentChanged += new

System.EventHandler(this.graphUI1_ContentChanged); this.BangVe.SelectedNodeChanged += new

System.EventHandler(this.graphUI1_SelectedNodeChanged);

// this.AcceptButton = this.cmdDuongDi; this.AutoScaleDimensions = new

System.Drawing.SizeF(9F, 19F); this.AutoScaleMode System.Windows.Forms.AutoScaleMode.Font; this.BackColor System.Drawing.Color.FromArgb(((int)(((byte)(192)))),

((int)(((byte)(255)))), ((int)(((byte)(255))))); this.CancelButton = this.cmdThoat; this.ClientSize = new System.Drawing.Size(823, 537); this.Controls.Add(this.label4); this.Controls.Add(this.cmdThoat); this.Controls.Add(this.groupBox2); this.Controls.Add(this.panel1); this.Controls.Add(this.BangVe); this.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular,

System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.FormBorderStyle System.Windows.Forms.FormBorderStyle.None; this.Icon ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Margin = new

System.Windows.Forms.Padding(4); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "frmMain"; this.StartPosition System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Chương trình minh họa thuật toán Floyd"; this.Load += new

System.EventHandler(this.Form1_Load); this.panel1.ResumeLayout(false); this.panel1.PerformLayout(); this.panel2.ResumeLayout(false); this.panel2.PerformLayout(); this.groupBox1.ResumeLayout(false); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.toolStrip1.ResumeLayout(false); this.toolStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout();

Kết quả chạy chương trình

Hình 13 : Kết quả chương trình

Ngày đăng: 27/02/2024, 16:16

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w