1. Trang chủ
  2. » Giáo Dục - Đào Tạo

BÀI tập lớn TOÁN rời rạc chủ đề thuật toán BFS và bài toán duyệt tất cả các thành phần liên thông của đồ thị

18 32 0
Tài liệu đã được kiểm tra trùng lặp

Đ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 đề Bài tập lớn Toán rời rạc chủ đề thuật toán BFS và bài toán duyệt tất cả các thành phần liên thông của đồ thị
Tác giả Dương Thanh Tỳ, Đinh Tiến Hựng, Lờ Quang Anh
Trường học Học viện Cễng Nghệ Bưu Chính Viễn Thông
Chuyên ngành Toán rời rạc
Thể loại Bài tập lớn
Năm xuất bản 2022
Thành phố Hà Nội
Định dạng
Số trang 18
Dung lượng 304 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNGKHOA VIỄN THÔNG BÀI TẬP LỚN TOÁN RỜI RẠC Chủ đề: Thuật toán BFS và bài toán duyệt tất cả các thành phần liên thông của đồ thị Giảng viên: Dương Tha

Trang 1

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG

KHOA VIỄN THÔNG

BÀI TẬP LỚN TOÁN RỜI RẠC

Chủ đề:

Thuật toán BFS và bài toán duyệt tất cả các

thành phần liên thông của đồ thị

Giảng viên: Dương Thanh Tú

Hà Nội 2022

Trang 2

I THUẬT TOÁN TÌM KIẾM THEO CHIỀU RỘNG (BFS)

- Thuật toán duyệt đồ thị ưu tiên chiều rộng (Breadth-first search – BFS) là một trong những thuật toán tìm kiếm cơ bản và thiết yếu trên đồ thị Mà trong đó những đỉnh nào gần đỉnh xuất phát hơn sẽ được duyệt trước

- Ứng dụng của BFS có thể giúp ta giải quyết tốt một số bài toán trong thời gian

và không gian tối thiểu Đặc biệt là bài toán tìm kiếm đường đi ngắn nhất từ một đỉnh gốc tới tất cả các đỉnh khác Trong đồ thị không có trọng số tất cả trọng số bằng nhau, thuật toán sẽ luôn trả ra đường đi ngắn nhất có thể Ngoài

ra, thuật toán này còn được dù để tìm các thành phần liên thông của đồ thị, hoặc kiểm tra đồ thị hai phía,…

II Mô tả thuật toán BFS

Đầu tiên ta thăm đỉnh nguồn ss

Việc thăm đỉnh ss sẽ phát sinh thứ tự thăm các đỉnh (u1,u2,…up)(u1,u2,

…up) kề với ss (những đỉnh gần ss nhất) Tiếp theo, ta thăm đỉnh u1u1, khi thăm đỉnh u1u1 sẽ lại phát sinh yêu cầu thăm những đỉnh (v1,v2,

…,vq)(v1,v2,…,vq) kề với u1u1 Nhưng rõ ràng những đỉnh vv này

“xa” ss hơn những đỉnh uu nên chúng chỉ được thăm khi tất cả những đỉnh uu đều đã được thăm Tức là thứ tự thăm các đỉnh sẽ là: s,u1,u2,

…,up,v1,v2,…,vq,…

Trang 3

- Mã giả của thuật toán BFS:

BFS(u){

// Step 1: Khởi tạo

Queue = Ø; // Tạo 1 hàng đợi rỗng.

Push(queue, u); // Đẩy u vào hàng đợi.

Visited[u] = true; // Đánh dấu là u đã được thăm.

// Step2: Lặp đến khi hàng đợi chưa rỗng.

Trang 4

While(queue != Ø)

v = pop(queue); // Lấy đỉnh ở đầu hàng đợi và xóa nó khỏi hàng

đợi <Thăm đỉnh v>

/ Duyệt tất cả các đỉnh kề với v mà chưa được thăm và đẩy vào hàng đợi for(int x : ke[v]){

if(!visited[x]){ // Nếu x chưa được

thăm push(queue, x);

visited[x] = true;

EndIf.

EndFor.

EndWhile.

/ Step3: Trả lại kết quả

Return(<tập đỉnh được duyệt>).

End.

Ví dụ: Cho đồ thị G = <V,E>, trình bày quá trình thuật toán BFS bắt đầu chạy từ đỉnh 1

Trang 5

STT Trạng thái Queue Các đỉnh được duyệt

Trang 6

5 10,4,6,7,9,8 1,2,3,5

III, Đánh giá độ phức tạp của thuật toán BFS

Trang 7

*)Độ phức tạp thời gian

Gọi |V||V| là số lượng đỉnh và |E||E| là số lượng cạnh của đồ thị

Trong quá trình BFSBFS, cách biểu diễn đồ thị có ảnh hưởng lớn tới chi phí về thời gian thực hiện giải thuật :

Nếu đồ thị biểu diễn bằng danh sách kề (vector g[]) :

o Ta có thể thực hiện thuật toán này một cách tối ưu nhất về mặt thời gian nhờ khả năng duyệt qua các đỉnh kề của mỗi đỉnh một cách hiệu quả

o Vì ta sử dụng mảng visit[] để ngăn việc đẩy một đỉnh vào hàng đợi nhiều lần nên mỗi đỉnh sẽ được thăm chính xác một lần duy nhất

Do đó, ta mất độ phức tạp thời gian O(|V|)O(|V|) dành cho việc thăm các đỉnh

o Bất cứ khi nào một đỉnh được thăm, mọi cạnh kề với đỉnh đó đều được duyệt, với thời gian dành cho mỗi cạnh là O(1)O(1) Từ phần

nhận xét của định lý Bắt tay (Handshaking lemma), ta sẽ mất độ

phức tạp thời gian O(|E|)O(|E|) dành cho việc duyệt các cạnh

o Nhìn chung, độ phức tạp thời gian của thuật toán này là O(|V|+| E|)O(|V|+|E|) Đây là cách cài đặt tốt nhất

Nếu đồ thị được biểu diễn bằng ma trận kề :

o Ta cũng sẽ mất độ phức tạp thời gian O(|V|)O(|V|) dành cho việc

thăm các đỉnh (giải thích tương tự như trên).

o Với mỗi đỉnh được thăm, ta sẽ phải duyệt qua toàn bộ các đỉnh của

đồ thị để kiểm tra đỉnh kề với nó Do đó, thuật toán sẽ mất độ phức tạp O(|V|2)O(|V|2)

Trang 8

IV THUẬT TOÁN BFS DUYỆT TẤT CÁC THÀNH PHẦN

LIÊN THÔNG CỦA ĐỒ THỊ

1 Đếm số thành phần liên thông của đồ thị vô hướng

- Nếu đồ thị là liên thông thì số thành phần liên thông của nó là 1 Tương ứng với thủ tục BFS(u) được gọi đúng 1 lần

- Nếu đồ thị không liên thông thì số thành phần không liên thông của nó >1 Suy ra có thể xác định số thành phần liên thông bằng cách gọi hàm BFS

- Thuật toán xác định số thành phần liên thông của đồ thị

Mã giả

Số TPLT(){

//Khởi tạo số TPLT ban đầu của đồ thị = 0

cnt = 0;

//Lặp

for(int i = 1; i <= n; i++) //Duyệt tất cả các đỉnh

Trang 9

++cnt; //Tăng số thành phần liên thông

BFS(i);

}

}

return cnt;

}

2 Tính liên thông mạnh trên đồ thị có hướng

- Đối với đồ thị vô hướng, nếu thủ tục BFS(u) = V thì ta kết luận đồ thị vô hướng liên thông

- Đối với đồ thị có hướng, nếu BFS(u) = V thì ta chỉ kết luận có đường đi từ u đến tất cả các đỉnh còn lại của đồ thị Nhiệm vụ là phải kiểm tra BFS(u) = V với mọi u thuộc V

Mã giả

Boolean strong-connective ( G = <V,E> ) {

ReInit(); //Với mọi u thuộc V thì visited[u] = false

Trang 10

For each u V do { //Lấy mỗi đỉnh thuộc V

If(BFS(u) != V)

Return false; //Đồ thị không liên thông mạnh

}

Reinit(); //Khởi tạo lại mảng visited[u]

Return true;//Đồ thị liên thông mạnh

}

Ví dụ: Cho ma trận kề của đồ thị có hướng G= <V, E> Xác định xem G

có liên thông mạnh hay không?

1 2 3 4 5 6 7 8 9 10 11 12 13

Trang 11

5 0 0 0 0 0 0 1 0 0 0 0 0 0

Đỉnh u ∈V BFS(u) BFS(u) = V ?

1 1, 6, 10, 11, 2, 3, 8, 9, 13, 4, 12, 5, 7 YES

2 2, 3, 8, 9, 13, 4, 12 ,5, 7, 11, 1, 6, 10 YES

3 3, 9, 13, 5, 7, 11, 2, 8, 4, 12, 1, 6, 10 YES

4 4, 1, 6, 10, 12, 2, 3, 8, 9, 13, 5, 7, 11 YES

5 5, 7, 11, 13, 2, 8, 9, 3, 4, 12, 1, 6, 10 YES

6 6, 10, 12, 2, 3, 4, 8, 9, 13, 1, 5, 7, 11 YES

Trang 12

7 7, 11, 13, 2, 8, 9, 3, 4, 12, 5, 1, 6, 10 YES

8 8, 4, 12, 1, 6, 10, 2, 3, 9, 13, 5, 7, 11 YES

9 9, 5, 7, 11, 13, 2, 8, 3, 4, 12, 1, 6, 10 YES

10 10, 2, 3, 8, 9, 13, 4, 12, 5, 7, 11, 1, 6 YES

11 11, 2, 8, 3, 4, 12, 9, 13, 1, 6, 10, 5, 7 YES

12 12, 4, 10, 1, 6, 2, 3, 8, 9, 13, 5, 7, 11 YES

Trang 13

13 13, 9, 11, 5, 7, 2, 8, 3, 4, 12, 1, 6, 10 YES

-Ta thấy cột ngoài cùng của bảng BFS(u) = V

thông mạnh

∀ u ∈V nên kết luận G là liên

ta kết luận đồ thị không liên

V Phần code ứng dụng của BFS để đếm số thành phần liên

thông của đồ thị và chỉ ra những thành phần liên thông

-Đề bài: Cho danh sách cạnh của đồ thị vô hướng G = <n, m > Xác định xem G có liên thông hay không và chỉ ra các thành phần liên thông của G

- Danh sách cạnh (input)

10 8 // 10 là số đỉnh, 8 là số cạnh

1 2

2 3

2 4

3 6

3 7

Trang 14

6 7

5 8

8 9

Code

#include<bits/stdc++.h>

using namespace std;

/ Duyệt tất cả các thành phần liên thông của đồ thị

int n, m; // n là số lượng đỉnh , m là số lượng cạnh

vector<int> adj[1001]; // vector adj để lưu danh sách kề của G = (n, m)

bool visited[1001]; // mảng visited dùng để đánh dấu các đỉnh đã

được thăm

void nhap(){

Trang 15

memset(visited, false, sizeof(visited)); cin >> n >> m;

for(int i = 1; i <= m; i++){

int x, y; cin >> x >> y;

adj[x].push_back(y);

adj[y].push_back(x);

}

}

void BFS(int u){

queue<int> q;

q.push(u);

visited[u] = true;

while(!q.empty()){

int v = q.front();

Trang 16

cout << v << ' ';

for(int x : adj[v]){

if(!visited[x]){

q.push(x);

visited[x] = true;

} }

}

}

void connectedComponent(){

int ans = 0; // Khởi tạo số TPLT của đồ thị for(int i = 1; i <= n; i++){

Trang 17

++ans;

cout << "Cac dinh thuoc thanh phan lien thong thu " << ans << " :\n";

BFS(i);

cout << endl;

} }

if(ans == 1)

cout << "Do thi lien thong !\n";

else

cout << "Do thi khong lien thong !\n";

}

int main(int argc, char const *argv[])

Trang 18

nhap();

connectedComponent();

return 0;

}

Out put:

Cac dinh thuoc thanh phan lien thong thu 1 : 123467

Cac dinh thuoc thanh phan lien thong thu 2 :

5 8 9

Cac dinh thuoc thanh phan lien thong thu 3 : 10

Do thi khong lien thong !

Ngày đăng: 20/12/2022, 09:08

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w