Nối tiếp phần 1, Bài giảng Toán rời rạc 2: Phần 2 tiếp tục cung cấp cho học viên những kiến thức về đồ thị Euler, đồ thị Hamilton; thuật toán tìm chu trình Euler; thuật toán tìm đường đi Euler; thuật toán tìm tất cả các chu trình Hamilton; cây khung của đồ thị; xây dựng cây khung của đồ thị dựa vào thuật toán DFS; bài toán tìm đường đi ngắn nhất; thuật toán Bellman-Ford;... Mời các bạn cùng tham khảo!
HỌC VIỆN CƠNG NGHỆ BƯU CHÍNH VIỄN THƠNG KHOA CƠNG NGHỆ THƠNG TIN BÀI GIẢNG TỐN RỜI RẠC NGUYỄN DUY PHƯƠNG HàNội 2016 CHƢƠNG ĐỒ THỊ EULER, ĐỒ THỊ HAMIL TON 4.1 Đồ thị Euler, đồ thị nửa Euler Định nghĩa Chu trình đơn đồ thị G qua cạnh đồ thị lần đƣợc gọi chu trình Euler Đƣờng đơn G qua cạnh lần đƣợc gọi đƣờng Euler Đồ thị đƣợc gọi đồ thị Euler có chu trình Euler Đồ thị có đƣờng Euler đƣợc gọi nửa Euler Rõ ràng, đồ thị Euler nửa Euler nhƣng điều ngƣợc lại khơng Ví dụ Xét đồ thị G1, G2, G3 Hình 4.1 a b a e d b a b c c d e c d G1 G2 e G3 Hình 6.1 Đồ thị vô hướng G1, G2, G3 Đồ thị G1 đồ thị Euler có chu trình Euler a, e, c, d, e, b, a Đồ thị G3 khơng có chu trình Euler nhƣng chứa đƣờng Euler a, c, d, e, b, d, a, b G3 nửa Euler G2 khơng có chu trình Euler nhƣ đƣờng Euler Ví dụ Xét đồ thị có hƣớng H1, H2, H3 Hình 4.2 a b a b a b d c c c H1 d e d H2 H3 Hình 4.2 Đồ thị có hướng H1, H2, H3 Đồ thị H2 đồ thị Euler chứa chu trình Euler a, b, c, d, e, a đồ thị Euler Đồ thị H3 khơng có chu trình Euler nhƣng có đƣờng Euler a, b, c, a, d, c nên đồ thị nửa Euler Đồ thị H1 khơng chứa chu trình Euler nhƣ chu trình Euler 4.2 Thuật tốn tìm chu trình Euler Để tìm chu trình Euler đồ thị ta sử dụng kết định lý sau Định lý Điều kiện cần đủ để đồ thị G= Euler Đồ thị vô hƣớng liên thông G= đồ thị Euler đỉnh G có bậc chẵn Đồ thị có 68 hƣớng liên thông yếu G= đồ thị Euler tất đỉnh có bán đỉnh bậc bán đỉnh bậc vào (điều làm cho đồ thị liên thông mạnh) 4.2.1 Chứng minh đồ thị Euler Đối với đồ thị vơ hƣớng, để chứng minh đồ thi có Euler hay không ta cần thực hiện: Kiểm tra đồ thị có liên thơng hay khơng? Điều dễ dàng thực cách kiểm tra DFS(u) = V BFS(u) = V ta kết luận đồ thị liên thông (u đỉnh đồ thị) Sử dụng tính chất ma trận kề biểu đồ thị vơ hƣớng để tính tốn bậc đỉnh 0 0 0 0 - Vì BFS(1) = { 1, 2, 6, 3, 5, 7, 4, 11, 8, 10, 12, 9, 13} = V Do vậy, G liên thông - Ta lại có : deg(1) = deg(13) = deg (2) = deg(3) = deg(4) = deg(5) = deg(6) = deg(7) = deg(8) = deg(9) = deg(10) = deg(11) = deg(12) = Chú ý: Tổng phần tử hàng u (cột u) bậc đỉnh u Ví dụ tổng phần tử hàng nên deg(1) = 1 1 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 Đối với đồ thị có hƣớng, để chứng minh đồ thi có Euler hay không ta cần thực hiện: Kiểm tra đồ thị có liên thơng yếu hay khơng? Điều dễ dàng thực cách kiểm tra tồn đỉnh u V để DFS(u) = V BFS(u) = V ta kết luận đồ thị liên thơng yếu Sử dụng tính chất ma trận kề biểu đồ thị có hƣớng để tính bán đỉnh bậc bán đỉnh bậc vào đỉnh Bán đỉnh bậc đỉnh u deg+(u) số số hàng u Bán đỉnh bậc vào đỉnh u deg-(u) số số cột u Ví dụ để chứng minh đồ thị có hƣớng đƣợc biểu diễn dƣới dạng ma trận kề nhƣ dƣới ta thực nhƣ sau: 69 + Vì BFS(1) = { 1, 2, 3, 5, 4, 11, 6, 7, 10, 12, 8, 9, 13} = V Do vậy, G liên thơng yếu + Ta lại có: deg+(2)= deg-(2)=deg+(3)= eg-(3) =2 deg+(4)=deg-(4)=deg+(5)=deg-(5) =2 deg+(6)=deg-(6)=deg+(7)=deg-(7) =2 deg+(8)=deg-(8)=deg+(9)=deg-(9) =2 deg+(10) = deg-(10) = deg+(11) = deg-(11) =2 deg+(12) = deg-(12) =2 deg+(1)=deg-(1)=deg-(13)=deg+(13) =1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 G liên thơng yếu có bán đỉnh bậc bán đỉnh bậc vào nên G đồ thị Euler 4.2.2 Biểu diễn thuật tốn tìm chu trình Euler Để tìm chu trình Euler đồ thị, ta thực theo thuật tốn Hình 4.3 dƣới đây: Thuật toán Euler-Cycle(u): Bƣớc (Khởi tạo) : stack = ; //Khởi tạo stack bắt đầu CE = ; //Khởi tạo mảng CE bắt đầu Push (stack, u) ; //Đƣa đỉnh u vào ngăn xếp Bƣớc (Lặp ): while (stack ) { //Lặp stack rỗng s = get(stack); //Lấy đỉnh đầu ngăn xếp if ( Ke(s) ) then { // Nếu danh sách Ke(s) chƣa rỗng t =< Đỉnh Ke(s)>; Push(stack, t)‟ //Đƣa t vào stack; E = E \ (s,t); // Loại bỏ cạnh (s,t); } else { //Trƣờng hợp Ke(s)= s = Pop(stack);// Đƣa s khỏi ngăn xếp s CE; //Đƣa s sang CE } } Bƣớc (Trả lại kết quả) : ; Hình 4.3 Thuật tốn tìm chu trình Euler bắt đầu đỉnh u 70 4.2.3 Kiểm nghiệm thuật tốn Ví dụ ta cần tìm chu trình Euler bắt đầu đỉnh u=1 đồ thị G = đƣợc biểu diễn dƣới dạng ma trận kề nhƣ dƣới Khi đó, bƣớc thực thuật tốn đƣợc thực nhƣ Bảng 4.1 (chú ý phần chứng minh ta thực trên) Bƣớc Trạng thái Stack Giá trị CE 1, 1, 2, 1, 2, 3, 1, 2, 3, 4,7 1, 2, 3, 4,7,5 1, 2, 3, 4,7,5,2 1, 2, 3, 4,7,5,2,6 1, 2, 3, 4,7,5,2,6,1 1, 2, 3, 4,7,5,2,6 1, 2, 3, 4,7,5,2,6,5 1, 2, 3, 4,7,5,2,6,5,3 1, 2, 3, 4,7,5,2,6,5,3,11 1, 2, 3, 4,7,5,2,6,5,3,11,4 1, 2, 3, 4,7,5,2,6,5,3,11,4,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,7 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,7,6 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,7 1,6 1, 2, 3, 4,7,5,2,6,5,3,11,4,8 1,6,7 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9 1,6,7 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10 1,6,7 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,8 1,6,7 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11,12 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11,12,9 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11,12,9,13 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11,12,9,13,12 1,6,7,8 1, 2, 3, 4,7,5,2,6,5,3,11,4,8,9,10,11,12,9,13,12,10 1,6,7,8 Đưa đỉnh Stack sang CE stack= 30 - CE = 1, 6, 7, 8, 10, 12, 13, 9, 12, 11, 10, 9, 8, 4, 11, 3, 5, 6, 2, 5, 7, 4, 3, 2, Lật ngược lại đỉnh CE ta chu trình Euler 1- 2- 3- 4- 7-5-2-6-5-3-11-4-8-9-10-11-12-9-13-12-10-8-7-6-1 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 4.2.4 Cài đặt thuật tốn 71 Chƣơng trình tìm chu trình Euler đồ thị bắt đầu tạo đỉnh u đồ thị vô hƣớng liên thông đƣợc cài đặt theo khuôn dạng đồ thị biểu diễn dƣới dạng ma trận kề Các thủ tục bao gồm: Thủ tục Init() : đọc liệu theo khuôn dạng biểu diễn ma trận kề Thủ tục Kiemtra(): Kiểm tra xem G có Euler hay khơng Thủ tục Euler-Cycle (u) : Xây dựng chu trình Euler bắt đầu đỉnh u #include #include #include #include #define MAX 50 #define TRUE #define FALSE int A[MAX][MAX], n, u=1; void Init(void){ int i, j;FILE *fp; fp = fopen("CTEULER.IN", "r"); fscanf(fp,"%d", &n); printf("\n So dinh thi:%d",n); printf("\n Ma tran ke:"); for(i=1; i