Lý thuyết đồ thị giải bài tập xác định thành phần liên thông mạnh giải bài tập xác định thành phần liên thông yếu xác định đồ thị liên thông Giải bài tập thuật toán Tarjan Cài đặt thuật toán Tarjan Biểu diễn thuật toán Tarjan Xác định số thành phần liên thông strongly connected component
TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN KHOA CÔNG NGHỆ THÔNG TIN – HỆ VB2 ĐÀO TẠO TỪ XA BÁO CÁO ĐỒ ÁN GVHD Lý Thuyết: Đặng Trần Minh Hậu GDHD Thực hành: Nguyễn Ngọc Thảo LỚP: Lý Thuyết Đồ Thị - CSC00008 NHÓM 32 MỤC LỤC A Nội dung lý thuyết Câu Câu B Nội dung cài đặt 13 A NỘI DUNG LÝ THUYẾT Câu 1: Định nghĩa thành phần liên thông mạnh (strongly connected component) đồ thị có hướng Một thành phần liên thơng mạnh đồ thị có hướng A + Một tiểu đồ thị (tiểu đồ thị có tính chất tối đại, tức không cạnh khác đồ thị có hướng cha (A) tồn tiểu đồ thị mà khơng làm tính chất liên thơng mạnh nó) + Tính chất tiểu đồ thị đồ thị có hướng tính chất liên thông mạnh (tất cặp đỉnh tiểu đồ thị có đường thuận tới đường ngược lại) Câu 2: Ta tìm thành phần liên thơng mạnh nhiều phương pháp khác (tham khảo Tài liệu 1) Chọn trình bày giải thuật để tìm thành phần liên thơng mạnh Phần trình bày cần nêu rõ vấn đề sàu: ý tưởng tổng quát giải thuật, bước thực giải thuật thể ví dụ cụ thể, đánh giá ngắn ưu điểm – khuyết điểm giải thuật Giải thuật Tarjan cho thành phần liên thông mạnh (Tarjan's strongly connected components algorithm) a Ý tưởng tổng quát giải thuật Giải thuật Tarjan thuật tốn tìm đường theo chiều sâu DFS kết hợp với tính chất thành phần liên thơng mạnh tính chất thành phần liên thông mạnh đồ thị có hướng với nhau, mục đích để xác định thành phần liên thông mạnh đồ thị có hướng Tính chất sử dụng + Trong thành phần liên thông mạnh đỉnh nhỏ kết nối từ đỉnh thành viên thành phần liên thông mạnh giống đỉnh nhỏ thành phần liên thông mạnh + Đỉnh kết nối nhỏ cố định cho thành phần liên thông mạnh (tức qua thành phần liên thông có đỉnh kết nối nhỏ mới) + Việc liên kết “quay trở lại’’ xuất thành phần liên thông mạnh thành phần liên thông mạnh khác ,chỉ xuất thành phần liên thông mạnh => Ghi lại đỉnh kết nối nhỏ đỉnh so sánh kết với đỉnh cha (node tỏa nhánh) để tìm đỉnh kết nối nhỏ từ node với với node cha, tương tự theo dòng đệ quy để lên node cha cao Sau hoàn thành thủ tục ghi lại thứ tự đỉnh đỉnh duyệt ghi lại đỉnh kết nối nhỏ ta đưa đỉnh vào Stack Nếu đỉnh kết nối nhỏ số thứ tự qua đỉnh ta kết luận đỉnh node bắt đầu cho thành phần liên thông mạnh, tất đỉnh thành phần liên thông mạnh có chung đỉnh kết nối nhỏ Trên đường (của đệ quy) ta in ghi lại (chứa) số thứ tự phần tử thành phần liên thông mạnh cách lấy từ Stack Các mảng biến cần khởi tạo chức gồm (ví dụ) Tên Loại Chức pointIndex Chứa thứ tự duyệt qua phần tử - [] mảng chiều int - Chiều dài: số đỉnh đồ thị pointLowIndex -[] mảng chiều int - Chiều dài: số đỉnh đồ thị -[] mảng chiều int - Chiều dài: xuất phát , độ dài +1 thêm phần tử, -1 giảm phần tử -[] mảng chiều bool - Chiều dài: số đỉnh đồ thị Stack isOnStack currentIndex Số nguyên (Tùy chọn) Count (Tùy chọn) MangTPLT Số nguyên -[] mảng Chứa số thứ tự đỉnh nhỏ mà đỉnh xét liên kết Chứa phần tử gán pointIndex pointLowIndex Chứa đánh dấu true false xác định phần tử cho vào Stack hay chưa Số thứ tự (sẽ tăng sau vòng chạy Tarjan) Biến đếm số thành phần liên thông Chưa thành phần liên thông, thành phần liên thông chứa đỉnh tplt Cũng DFS, thuật toán Tarjan gồm hàm main để khởi tạo thuật toán (duyệt đỉnh v tập đỉnh V đồ thị) hàm Tarjan nhằm đánh số phần tử đỉnh, đánh số phần tử đỉnh kết nối phần tử đỉnh đồ thị, cho vào stack b Các bước thực giải thuật thể ví dụ cụ thể Giả sử có đồ thị có hướng bên dưới, áp dụng Tarjan để tìm thành phần liên thơng mạnh Bước thực Diễn giải Bước 1: Set up mảng biến chứa - CurrentIndex = thông tin phần tử duyệt hàm - Cho đỉnh a đỉnh đồ thị pointIndex[a] = -1 MainTarjan set giá trị cho pointLowIndex[a] = -1 mảng biến cho tất đỉnh Stack = [] isOnStack[a] = false - Hàm main có dạng (mã giả) Bước 2: Chạy hàm Tarjan cho giá trị đỉnh đầu duyệt đến hết đồ thị (check duyệt chưa mảng pointIndex) - pointIndex[0] = -1 => Tarjan(0) 0 T x pointIndex pointLowIndex isOnStack Stack Bước 3: Xét cho đỉnh mà đỉnh chạy Tarjan kết nối với Nếu đỉnh chưa qua (pointIndex = -1), chạy Tarjan đỉnh Nếu đỉnh qua (pointIndex ≠ -1) , tìm đỉnh nhỏ mà đỉnh cha kết nối (min poinLowIndex) Khi xong việc xét đỉnh , tiến -1 -1 F -1 -1 F -1 -1 F -1 -1 F -1 -1 F -1 -1 F Hàm Tarjan có dạng (mã giả) hành so sánh index lowIndex để check xem đỉnh có phải đỉnh nhỏ thành phần liên thông mạnh hay không, từ xuất phần tử Stack thành phần liên thơng mạnh Các bước chi tiết bước Bước 3.1 - Đỉnh kết nối với => Chạy Tarjan cho , pointIndex[0] = -1 Tarjan(1) pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x -1 -1 F -1 -1 F -1 -1 F -1 -1 F -1 -1 F Bước 3.2 - Đỉnh kết nối với 2,4,6 Chạy Tarjan cho 2, pointIndex[2] = -1 Tarjan(2) pointIndex pointLowIndex isOnStack Stack Bước 3.3 0 T x 1 T x 2 T x -1 -1 F -1 -1 F -1 -1 F -1 -1 F - Đỉnh kết nối với Chạy Tarjan cho 3, pointIndex[3] = -1 Tarjan(3) pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 T x 3 T x -1 -1 F -1 -1 F -1 -1 F - Đỉnh kết nối với 2,4 - Xét đỉnh pointIndex[2] ≠ -1 có “quay lại’’ tức 2,3 nằm thành phần liên thông Cho pointLowIndex[3] = min(pointLowIndex[3], pointIndex[2]) = 0 pointIndex pointLowIndex isOnStack T T Stack x x - Xét đỉnh 4, pointIndex[4] = -1 Chạy Tarjan cho pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 T x 3 T x -1 -1 F 2 T x 36 T x -1 -1 F -1 -1 F 4 25 -1 -1 T F x -1 -1 F Bước 3.4 - Đỉnh kết nối với Chạy Tarjan cho 5, pointIndex[5] = -1 Tarjan(5) 5 pointIndex -1 pointLowIndex 2 -1 isOnStack T T T T T T F Stack x x x x x x - Đỉnh kết nối với - Xét đỉnh pointIndex[4] ≠ -1 có “quay lại’’ tức 4,5 nằm thành phần liên thông Cho pointLowIndex[5] = min(pointLowIndex[5], pointIndex[4]) = 4 6 pointIndex -1 pointLowIndex 2 4 -1 isOnStack T T T T T T F Stack x x x x x x - Vì sau khơng có đỉnh khác ngồi kết thúc vịng Bước 3.5 lặp xét đỉnh cho - Tiến hành check index lowIndex Vì pointIndex[5] = ≠ pointLowIndex[5] = End Tarjan cho - Sau end Tarjan(5) quay lại Tarjan(4) - Cho pointLowIndex[4] = min(pointLowIndex[4], pointLowIndex [5]) = - Vì khơng có đỉnh khác ngồi kết thúc vòng lặp xét đỉnh cho - Tiến hành check index lowIndex Vì pointIndex[4] = pointLowIndex[4] = => node nhỏ thành phần liên thông tiến hành xuất thành phần liên thông 4,5 pointIndex -1 pointLowIndex 2 4 -1 isOnStack T T T T T T F Stack x x x x x x Xuất thành phần liên thông end Tarjan cho - Cho w = -1, tăng biến đếm thành phần liên thông - Xét phần tử stack (từ phần tử cuối mảng đổ lên), khác 5 Cho w = phần tử cuối stack Tắt false cho w Remove w từ Stack Xuất đưa w vào list thành phần liên thông chuẩn bị sẵn, tăng biến đếm thành phần liên thông 0 T x pointIndex pointLowIndex isOnStack Stack Bước 3.6 1 T x 2 T x 3 T x 4 F 5 F -1 -1 F - Sau end Tarjan(4) quay lại Tarjan(3) - Cho pointLowIndex[3] = min(pointLowIndex[3], pointLowIndex [4]) = - Vì khơng có đỉnh khác ngồi 2,4 => kết thúc vịng lặp xét đỉnh cho - Tiến hành check index lowIndex - Vì pointIndex[3] = ≠ pointLowIndex[3] = => End Tarjan cho 0 T x pointIndex pointLowIndex isOnStack Stack 1 T x 2 T x 3 T x 4 F 5 F -1 -1 F Bước 3.7 - Sau end Tarjan(3) quay lại Tarjan(2) - Cho pointLowIndex[2] = min(pointLowIndex[2], pointLowIndex [3]) = - Vì khơng có đỉnh khác ngồi kết thúc vòng lặp xét đỉnh cho - Tiến hành check index lowIndex - Vì pointIndex[2] = pointLowIndex[2] = => node nhỏ thành phần liên thông => Tiến hành xuất thành phần liên thông 2,3 pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 T x 3 T x 4 F 5 F -1 -1 F Xuất thành phần liên thông end Tarjan cho - Cho w = -1, tăng biến đếm thành phần liên thông - Xét phần tử stack (từ phần tử cuối mảng đổ lên), khác Cho w = phần tử cuối stack Tắt false cho w Remove w từ Stack Xuất đưa w vào list thành phần liên thông chuẩn bị sẵn pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 F 3 F 4 F 5 F -1 -1 F Bước 3.8 - Sau end Tarjan(2) quay lại Tarjan(1) - Cho pointLowIndex[1] = min(pointLowIndex[1], pointLowIndex [2]) = Hoàn thành xét đỉnh cho - Tiến hành xét đỉnh 4, - Vì pointIndex[4] ≠ -1 => Cho pointIndex[1] = min(pointLowIndex[1], pointIndex [4]) = => Hoàn thành xét đỉnh cho - Vì pointIndex[6] = -1 Chạy Tarjan(6) pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 F 3 F 4 F 5 F 6 T x - Đỉnh có kết nối với + Xét pointIndex[0] ≠ -1 Cho poinLowIndex[6] = min(pointLowIndex[6],pointIndex[0]) = + Xét pointIndex[2] ≠ -1 Cho poinLowIndex[6] = min(pointLowIndex[6],pointIndex[2]) = Hoàn thành xét đỉnh 0,2 cho - Vì khơng có đỉnh khác ngồi 0,2 => kết thúc vịng lặp xét đỉnh cho - Tiến hành check index lowIndex - Vì pointIndex[6] = ≠ pointLowIndex[6] = => => End Tarjan cho pointIndex pointLowIndex isOnStack Stack 0 T x 1 T x 2 F 3 F 4 F 5 F 6 T x Bước 3.9 - Sau end Tarjan(6) quay lại Tarjan(1), poinLowIndex[1] = min(pointLowIndex[1],pointLowIndex[6]) =0 - Vì khơng có đỉnh khác ngồi 2,4,6 kết thúc vòng lặp xét đỉnh cho - Tiến hành check index lowIndex - Vì pointIndex[1] = ≠ pointLowIndex[1] = => End Tarjan cho 1 Bước 3.10 3 pointIndex pointLowIndex 0 2 4 isOnStack T T F F F F T Stack x x x - Sau end Tarjan(1) quay lại Tarjan(0) poinLowIndex[0] = min(pointLowIndex[0],pointLowIndex[1]) = - Vì khơng có đỉnh khác ngồi kết thúc vịng lặp xét đỉnh cho - Tiến hành check index lowIndex Vì pointIndex[0] = pointLowIndex[0] = => node nhỏ thành phần liên thông => tiến hành xuất thành phần liên thông 0,1,6 pointIndex pointLowIndex 0 2 4 isOnStack T T F F F F T Stack x x x Xuất thành phần liên thông end Tarjan cho - Cho w = -1, tăng biến đếm thành phần liên thông - Xét phần tử stack (từ phần tử cuối mảng đổ lên), khác Cho w = phần tử cuối stack Tắt false cho w Remove w từ Stack Xuất đưa w vào list thành phần liên thông chuẩn bị sẵn pointIndex pointLowIndex isOnStack 0 F 1 F 2 F 3 F 4 F 5 F 6 F Stack Bước 3.11 Khi end Tarjan 0, tiếp tục phần tử khác vòng for hàm Main đồ đồ thị nhiều thành phần liên thơng (trong trường hợp ví dụ nằm thành phần liên thơng) nên end for Main Tarjan Kết thúc thuật toán c Đánh giá ưu điểm khuyết điểm giải thuật Tarjan Ưu điểm - Chỉ lần duyệt qua DFS, nhanh thuật tốn Kosaraju - Khơng cần đảo chiều hướng mũi tên đồ thị Kosaraju - Dễ áp dụng Khuyết điểm - Chỉ xuất kết tìm node đỉnh nhỏ thành phần liên thông mạnh - Thứ tự đỉnh thành phần liên thơng mạnh tìm bị ngược B NỘI DUNG CÀI ĐẶT Cho đồ thị có hướng khơng có cạnh bội khơng có cạnh khuyên Danh sách kề biểu diễn đồ thị cho có định dạng sau: ▪ Dịng chứa số nguyên n (n > 2) thể số đỉnh củà đồ thị ▪ n dòng chứa thông tin danh sách kề củà đỉnh đến đỉnh n-1 ▪ Danh sách kề đỉnh i biểu diễn mi + số ngun, trơng số ngun số lượng đỉnh có cạnh nối xuất phát từ đỉnh i (tức mi) số nguyên mục đỉnh kề (chỉ mục tính từ 0) 1) Xác định đồ thị cho liên thông mạnh, liên thông phần, liên thông yếu hay không liên thông Tham khảo Tài liệu [2] 2) Xác định thành phần liên thơng mạnh có đồ thị Với thành phần liên thông, cho biết mục củà đỉnh thuộc thành phần liên thơng Tham khảo Tài liệu [3] Kết làm Xác định loại đồ thị, xác định loại thành phần liên thơng mạnh có đồ thị, phần minh họa kết xuất + Đồ thị liên thông mạnh: (hình 2.1.1) I Hình 2.1.1 + Đồ thị liên thơng phần (hình 2.1.2) Hình 2.1.2 + Đồ thị liên thơng yếu (hình 2.1.3) Hình 2.1.3 + Đồ thị khơng liên thơng (hình 2.1.4) Hình 2.1.4 II Những ghi quan trọng Chương trinh gồm class (Program.cs) nơi gọi file.txt xuất kết class chức Lưu ý copy đường dẫn vào hàm main để chương trình truy xuất vào file (bơi màu vàng) * * ví dụ đường dẫn: @"D:\VB KHTN\Lý thuyết đồ thị\Bai Tap\Đồ án 01\SOURCE\lienthongtungphan.txt" Hình 2.1.5 Các class hàm chức gồm có Class Bao gồm Program - Hàm Main: Hàm chạy chương trình Graph - struct AdjacencyList : Kiểu liệu tự định nghĩa cho AdjacenyList Handler - Hàm InputAndStore : Đọc danh sách kề vào chương trình - Hàm ConvertToPathMatrix: Chuyển đổi AdjacencyList qua PathMatrix - Hàm ConvertToUndirectedGraph: Chuyển đổi đồ thị dạng AdjacencyList qua AdjacencyMatrix DFS Tarjan (Hình 2.1.7) Connected Component TypeCheck (Hình 2.1.6) - Hàm DFSFindPath, DFSMainFindPath: DFS tìm đường - Hàm DFSFindComponents, DFSPrintComponents, DFSMainFindComponents: DFS xác định liên thông hay không liên thơng - Hàm Min: Tìm Min số a,b - Hàm MainTarJan, TarjanSCC, PrintSCCArr: thuật toán Tarjan xác định thành phần liên thơng mạnh - Hàm connectedComponentTypeCheck: hàm xác định loại thành phần liên thông - Hàm strongConnectedComponentCheck, unilaterallyConnectedComponentCheck, noConnectedComponentCheck: check trường hợp mạnh , phần không liên thông => Hàm tổng (connectedComponentTypeCheck) check loại đồ thị liên thông loại đồ thị liên thơng yếu Hình 2.1.6 Hình 2.1.7 ... 0) 1) Xác định đồ thị cho liên thông mạnh, liên thông phần, liên thông yếu hay không liên thông Tham khảo Tài liệu [2] 2) Xác định thành phần liên thơng mạnh có đồ thị Với thành phần liên thông, ... chất thành phần liên thông mạnh tính chất thành phần liên thơng mạnh đồ thị có hướng với nhau, mục đích để xác định thành phần liên thông mạnh đồ thị có hướng Tính chất sử dụng + Trong thành phần. .. phần liên thông mạnh đỉnh nhỏ kết nối từ đỉnh thành viên thành phần liên thông mạnh giống đỉnh nhỏ thành phần liên thơng mạnh + Đỉnh kết nối nhỏ cố định cho thành phần liên thông mạnh (tức qua thành