Giải pháp cũ thường làm:Khi giảng dạy phần "BFS và các ứng dụng" cho học sinh THPT thường gặp phải haivấn đề chính đó là chưa có hệ thống bài tập rõ ràng và chuyên đề về đồ thị tương đối
Trang 1SỞ GIÁO DỤC VÀ ĐÀO TẠO NINH BÌNH
TRƯỜNG THPT CHUYÊN LƯƠNG VĂN TỤY
- -SÁNG KIẾN KINH NGHIỆM
ĐỀ TÀI: “BFS VÀ CÁC ỨNG DỤNG”
NĂM HỌC : 2022-2023
Trang 2Phần A: BẢN TÓM TẮT SÁNG KIẾN KINH NGHIỆM
* Về vấn đề thiếu hệ thống bài tập rõ ràng, thông thường các giáo viên chỉ giải thích lý
thuyết và cung cấp một số ví dụ để học sinh có thể hiểu và áp dụng vào thực tế Tuy nhiên,điều này khiến cho học sinh gặp khó khăn trong việc nắm vững kiến thức và áp dụng vào cácbài tập thực tế
Bài tập Tin học liên quan tới BFS trong các đề thi học sinh giỏi cấp tỉnh thường đadạng Để có tài liệu dạy đội tuyển, giáo viên thường phải dày công tìm tòi từ nhiều nguồn tưliệu Khi soạn giảng, giáo viên bắt buộc phải tham khảo rất nhiều tài liệu từ nhiều phươngtiện, do đó mất rất nhiều thời gian và công sức, tốn kém nhiều tiền bạc
* Về vấn đề chuyên đề về đồ thị tương đối mới và khó đối với đại bộ phận giáo viên dạy
Tin học trong tỉnh Do đó nhiều giáo viên cảm thấy khó khăn trong việc giảng dạy vì không
có đủ kiến thức về đồ thị để giải thích và hướng dẫn cho học sinh Giáo viên cũng phải đốimặt với nhiều thách thức trong việc giảng dạy phần "BFS và các ứng dụng" Một số khó khănthường gặp là:
Thiếu tài liệu và sách báo chuyên ngành: Việc tiếp cận các tài liệu và sách báo chuyênngành về đồ thị và thuật toán BFS không phải là dễ dàng Vì tài liệu trên nguồn internet là rờirạc Điều này khiến cho các giáo viên khó có thể nắm bắt và cập nhật kiến thức mới nhấttrong lĩnh vực này
Thiếu kinh nghiệm giảng dạy: Nhiều giáo viên chưa có đủ kinh nghiệm và kỹ năngtrong việc giảng dạy phần "BFS và các ứng dụng" Điều này khiến cho việc truyền đạt kiếnthức và hướng dẫn cho học sinh gặp nhiều khó khăn
b Giải pháp mới cải tiến:
Nhóm tác giả sử dụng hệ thống kiến thức thông qua việc phân loại các dạng BFS bằngthuật toán và các bài tập ứng dụng Do đó BFS và các ứng dụng được xây dựng là rất logic, đadạng, phong phú, thể hiện kiến thức bao chùm từ cơ bản đến phức tạp, từ dễ đến khó, phù hợpvới trình độ nhận thức của học sinh, có thể dành cho nhiều đối tượng học sinh dự thi học sinhgiỏi THPT
Đối với học sinh lần đầu tiên tiếp cận với lý thuyết đồ thị sẽ không tránh khỏi nhữngngỡ ngàng, lạ lẫm, có phần trừu tượng khó hiểu Để giúp đỡ giải quyết vấn đề đó, trongchuyên đề này nhóm tác giả trình bày về phương pháp duyệt theo chiều rộng (BFS) trên đồ thị
Trang 3và các ứng dụng Phần lý thuyết về cơ bản đã rất rõ ràng trong cuốn Tài liệu giáo khoa chuyênTin, nhóm tác giả trình bày lại theo hướng tiếp cận khác nhằm mục đính giúp cho giáo viên vàhọc sinh có thể dễ dàng nghiên cứu hơn Trong nội dung nghiên cứu, nhóm tác giả trình bày
về những ứng dụng cơ bản của BFS và các bài tập cho học sinh luyện tập, các bài tập đượcsắp xếp theo mức độ từ dễ tới khó, mỗi bài có hướng dẫn sơ lược, có link test, một số bài chỉ
để link để giáo viên và học sinh tham khảo thêm Nội dung nghiên cứu này được dùng để dạycác em học sinh lớp 10 chuyên Tin, mới học đến phần lý thuyết cơ bản về đồ thị và các đốitượng học sinh ở các trường phổ thông trong tỉnh ôn thi HSG tiếp cận
Hệ thống bài tập lựa chọn đưa vào trong nội dung nghiên cứu này được sưu tầm chủ yếunguồn trên SPOJ và VNOI để thuận tiện cho bạn đọc luyện tập Code mẫu một phần là củachính tác giả, một phần được tham khảo trên Internet
Trong mỗi dạng bài theo mức độ nhận thức, bài tập được sắp xếp theo từng chủ đề vớicùng mức độ kiến thức
3 Hiệu quả kinh tế, xã hội dự kiến đạt được
a Hiệu quả kinh tế.
“BFS và các ứng dụng” không gây tốn kém về kinh tế của phụ huynh học sinh và nhàtrường, vì vậy nó có thể áp dụng thường xuyên, liên tục ở các tiết học trên lớp; góp phần tíchcực chuyển biến cách dạy, học của giáo viên và học sinh chuyên tin cũng như các đối tượnghọc sinh khá giỏi không thuộc lớp chuyên, trường chuyên
b Hiệu quả xã hội.
- Nhiều học sinh đã tự giải được các bài tập trong cuốn Tài liệu giáo khoa chuyêntin và một số bài tập trên các trang nguồn SPOJ, VNOI
- Nhiều học sinh đã thực sự yêu thích, đam mê môn Tin học Qua đó các em cóđịnh hướng nghề nghiệp sau này
- Kết quả thu được thể hiện qua các bài kiểm tra qua hai năm học rất khả quan Cụthể:
Kết quả kiểm tra giữa học kì II năm học 2021 – 2022 của lớp thực nghiệm 10chuyên tin K63
Trang 4ớp
Sĩ số
Số lượng
4 Điều kiện và khả năng áp dụng
Chúng tôi xin cam đoan mọi thông tin nêu trong đơn là trung thực, đúng sự thật, nếu saichúng tôi xin hoàn toàn chịu trách nhiệm
Trang 5Phần B: PHỤ LỤC (Mục đích: Trình bày chi tiết các giải pháp trong sáng kiến)
Trang 61 Giới thiệu
Trong chuyên đề này tôi trình bày về phương pháp duyệt theo chiều rộng (BFS) trên
đồ thị và các ứng dụng Phần lý thuyết về cơ bản đã rất rõ ràng trong cuốn Tài liệu giáo khoachuyên Tin, tôi trình bày lại theo hướng tiếp cận của cá nhân, tài liệu được dùng để dạy các
em học sinh lớp 10 chuyên Tin, mới học đến phần lý thuyết cơ bản về đồ thị
Đối với học sinh lần đầu tiên tiếp cận với lý thuyết đồ thị sẽ không tránh khỏi nhữngngỡ ngàng, lạ lẫm, có phần trừu tượng khó hiểu, để giúp đỡ giải quyết vấn đề đó, trong phạm
vi chuyên đề chỉ trình bày những ứng dụng cơ bản của BFS và các bài tập cho học sinh luyệntập, các bài tập được sắp xếp theo mức độ từ dễ tới khó, mỗi bài có hướng dẫn sơ lược, cólink test, một số bài chỉ để link để bạn đọc tham khảo thêm
Các bài tập được sưu tầm chủ yếu nguồn trên SPOJ và VNOI để thuận tiện cho bạnđọc luyện tập Code mẫu một phần là của chính tác giả, một phần được tham khảo trênInternet Do hạn chế về thời gian cũng như trình độ, chuyên đề phản ánh góc tiếp cận của cánhân trong quá trình dạy học phần BFS nên còn có nhiều thiếu sót, rất mong nhận được ý kiếnđóng góp của bạn đọc để hoàn thiện hơn Xin chân thành cảm ơn
Trang 72 Yêu cầu kiến thức
Để tiếp cận được với chuyên đề này, yêu cầu người học cần chuẩn bị trước một số khái niệm về lý thuyết đồ thị, bao gồm:
Một đồ thị kí hiệu là G = (V,E)
Trong đó:
V là tập các đỉnh của đồ thị Kí hiệu |V| = N là số đỉnh của đồ thị
E là tập các cạnh của đồ thị Kí hiệu |E| = M là số cạnh của đồ thị
Hai cạnh song song:
Là hai cạnh cùng nối hai đỉnh u, v
Trang 8Trong đồ thị vô hướng, bậc của đỉnh v trong đồ thị G, ký hiệu dG(u), là số cạnh liên thuộc với v, trong đó, khuyên được tính hai lần
Hệ quả: Trong đồ thị vô hướng, số đỉnh bậc lẻ là chẵn
Trong đồ thị có hướng, ta định nghĩa bán bậc ra của u là số cung đi ra khỏi nó, kí
hiệu d+ G(u), bán bậc vào của u là số cung đi vào đỉnh đó,
kí hiệu d- G(u)
Giả sử G=(V, E) là đồ thị có hướng, khi đó tổng các bán bậc vào bằng tổng các bánbậc ra và bằng số cung của đồ thị
Đường đi và chu trình:
Một dãy các đỉnh P = (p0, p1, …, pk) sao cho (Pi-1, Pi) ∊ E, ∀i: 1 ≤ i ≤ k được gọi làmột đường đi
Một đường đi là chu trình khi p0 = pk
Biểu diễn đồ thị trên máy tính
Có nhiều cách để biểu diễn đồ thị trên máy tính, tùy thuộc vào tính chất của đồ thịhoặc thuật toán áp dụng với đồ thị… Ta cũng có thể lưu kèm theo các thông tin như trọng số,giá trị phù hợp với từng cạnh
*Biển diễn đồ thị theo ma trận kề
*Biểu diễn đồ thị bằng danh sách cạnh
*Biểu diễn đồ thị bằng danh sách kề
*Biểu diễn đồ thị bằng danh sách liền thuộc
Trang 93 BFS và ứng dụng
3.1 Thuật toán duyệt đồ thị ưu tiên chiều rộng
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ônggian 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ố hoặc tất cả trọng số bằng nhau, thuật toán sẽ luôntrả ra đường đi ngắn nhất có thể Ngoài ra, thuật toán này còn được dùng để tìm các thànhphần liên thông của đồ thị, hoặc kiểm tra đồ thị hai phía, …
Ý tưởng
Với đồ thị không trọng số và đỉnh nguồn s Đồ thị này có thể là đồ thị có hướng hoặc vôhướng, điều đó không quan trọng đối với thuật toán
Có thể hiểu thuật toán như một ngọn lửa lan rộng trên đồ thị:
Ở bước thứ 0, chỉ có đỉnh nguồn s đang cháy
Ở mỗi bước tiếp theo, ngọn lửa đang cháy ở mỗi đỉnh lại lan sang tất cả các đỉnh kề với nó
Trong mỗi lần lặp của thuật toán, "vòng lửa" lại lan rộng ra theo chiều rộng Nhữngđỉnh nào gần s hơn sẽ bùng cháy trước
Chính xác hơn, thuật toán có thể được mô tả như sau:
Đầu tiên ta thăm đỉnh nguồn s
Việc thăm đỉnh s sẽ phát sinh thứ tự thăm các đỉnh (u1,u2,…up) ( v1,v2,…,vq) kề
với s (những đỉnh gần s nhất) Tiếp theo, ta thăm đỉnh u1, khi thăm đỉnh u1 sẽ lại phát sinh yêu cầu thăm những đỉnh (v1,v2,…,vq) (v1,v2,…,vq) kề với u1 Nhưng rõ ràng những đỉnh v này “xa” s hơn những đỉnh u nên chúng chỉ được thăm khi tất cả những đỉnh u đều đã được thăm Tức là thứ tự thăm các đỉnh sẽ là: s, u1,u2,…up, v1,v2,…,vq,
…
Trang 10Thuật toán tìm kiếm theo chiều rộng sử dụng một danh sách để chứa những đỉnh đang
“chờ” thăm Tại mỗi bước, ta thăm một đỉnh đầu danh sách, loại nó ra khỏi danh sách và chonhững đỉnh kề với nó chưa được thăm xếp hàng vào cuối danh sách Thuật toán sẽ kết thúckhi danh sách rỗng
Thuật toán
Thuật toán sử dụng một cấu trúc dữ liệu hàng đợi (queue) để chứa các đỉnh sẽ được
duyệt theo thứ tự ưu tiên chiều rộng
Bước 1: Khởi tạo
Các đỉnh đều ở trạng thái chưa được đánh dấu Ngoại trừ đỉnh nguồn s đã được đánh dấu
Một hàng đợi ban đầu chỉ chứa 1 phần tử là s
Bước 2: Lặp lại các bước sau cho đến khi hàng đợi rỗng:
Lấy đỉnh u ra khỏi hàng đợi
Xét tất cả những đỉnh v kề với u mà chưa được đánh dấu, với mỗi đỉnh v đó:
o Đánh dấu v đã thăm
o Lưu lại vết đường đi từ u đến v
o Đẩy v vào trong hàng đợi (đỉnh v sẽ chờ được duyệt tại những bước sau)
Bước 3: Truy vết tìm đường đi.
Mô tả
Xét đồ thị sau đây, với đỉnh nguồn s=1 :
Trang 11 Quá trình:
Trang 12Cài đặt
Cấu trúc dữ liệu:
Biến maxN - Kích thước mảng
Mảng d[] - Mảng lưu lại khoảng cách từ đỉnh nguồn đến mọi đỉnh
Mảng par[] - Mảng lưu lại vết đường đi
Mảng visit[] - Mảng đánh dấu các đỉnh đã thăm
Vector g[] - Danh sách cạnh kề của mỗi đỉnh
Hàng đợi q - Chứa các đỉnh sẽ được duyệt theo thứ tự ưu tiên chiều rộng
int n; // Số lượng đỉnh của đồ thị
int d[maxN], par[maxN];
bool visit[maxN];
vector <int> g[maxN];
void bfs(int s) { // Với s là đỉnh xuất phát (đỉnh nguồn)
int u = q.front(); q.pop();
for (auto v : g[u]) {
Cài đặt truy vết đường đi từ đỉnh nguồn s đến đỉnh u:
if (!visit[u]) cout << "No path!";
Trang 13else {
vector <int> path;
for (int v = u; v != -1; v = par[v])
3.2 Các đặc tính của thuật toán BFS
Nếu sử dụng một ngăn xếp (stack) thay vì hàng đợi (queue) thì ta sẽ thu được thứ tự duyệt đỉnh của thuật toán tìm kiếm theo chiều sâu (Depth First Search – DFS) Đây chính
là phương pháp khử đệ quy của DFS để cài đặt thuật toán trên các ngôn ngữ không cho phép
đệ quy
Định lí: Thuật toán BFS cho ta độ dài đường đi ngắn nhất từ đỉnh nguồn tới mọi đỉnh (với khoảng cách tới đỉnh u bằng d[u]) Trong thuật toán BFS, nếu đỉnh u gần đỉnh
nguồn hơn đỉnh v, thì u sẽ được thăm trước
Chứng minh: Trong BFS, từ một đỉnh hiện tại, ta luôn đi thăm tất cả các đỉnh kề với
nó trước, sau đó thăm tất cả các đỉnh cách nó một đỉnh, rồi các đỉnh cách nó hai đỉnh, v.v… Như vậy, nếu từ một đỉnh u khi ta chạy BFS, quãng đường đến đỉnh v luôn là quãng đường đi qua ít cạnh nhất
Trang 143.3 Ứng dụng BFS để xác định thành phần liên thông
Bài toán 1
BFS - Đếm số thành phần liên thông
Đề bài
Cho đơn đồ thị vô hướng gồm n đỉnh và m cạnh (1≤n,m≤105), các đỉnh được đánh số
từ 1 tới n Tìm số thành phần liên thông của đồ thị
Thuật toán ứng dụng BFS để xác định thành phần liên thông:
Bước 0: Khởi tạo số lượng thành phần liên thông bằng 0.
Bước 1: Xuất phát từ một đỉnh chưa được đánh dấu của đồ thị Ta đánh dấu đỉnh xuất
phát, tăng số thành phần liên thông thêm 1
Bước 2: Từ một đỉnh i đã đánh dấu, ta đánh dấu tất cả các đỉnh j kề với i mà j chưa
được đánh dấu
Bước 3: Thực hiện bước 2 cho đến khi không còn thực hiện được nữa.
Bước 4: Nếu số số đỉnh đánh dấu bằng n (mọi đỉnh đều được đánh dấu) kết thúc thuật
toán và trả về số thành phần liên thông, ngược lại quay về bước 1
Mô tả
Cài đặt
Cấu trúc dữ liệu:
Hằng số maxN = 100007
Biến components - Số lượng thành phần liên thông
Mảng visit[] - Mảng đánh dấu các đỉnh đã thăm
Trang 15 Vector g[] - Danh sách cạnh kề của mỗi đỉnh.
Hàng đợi q - Chứa các đỉnh sẽ được duyệt theo thứ tự ưu tiên chiều rộng
Độ phức tạp của thuật toán là O(n+m)
3.4 Thuật toán loang (Flood Fill)
Trang 16Thuật toán loang (thuật toán vết dầu loang) là một kĩ thuật sử dụng BFS để tìm tất cả
các điểm có thể đi tới Điểm khác biệt giữa Loang so với đa số những bài BFS là ta không
phải tìm chi phí nhỏ nhất
Thuật toán loang được dùng khá nhiều trong tin học, điển hình là thuật toán loang trên
ma trận được ứng dụng để đếm số thành phần liên thông trên ma trận Ngoài ra, nó còn ứng dụng trong các bài toán thực tế như các bài toán tìm đường đi, game dò mìn, game line98,…
Gọi là thuật toán loang vì nguyên lí của thuật toán này rất giống với hiện tượng loangcủa chất lỏng Khi ta nhỏ dầu xuống một mặt phẳng, vết dầu có thể loang ra những khu vựcxung quanh Tương tự, thuật toán loang trên ma trận cũng vậy, ta sẽ duyệt một ô trên ma trận
và sau đó duyệt các điểm xung quanh nó và loang dần ra để giải quyết bài toán
Bài toán 2
Đề bài
Một tai nạn hàng hải đã khiến dầu tràn ra biển Để có được thông tin về mức độ nghiêmtrọng của thảm họa này, người ta phải phân tích các hình ảnh chụp từ vệ tinh, từ đó tính toánchi phí khắc phục cho phù hợp Đối với điều này, số lượng vết dầu loang trên biển và kíchthước của mỗi vết loang phải được xác định Vết loang là một mảng dầu nổi trên mặt nước
Để tiện cho việc xử lí, hình ảnh được chuyển đổi thành một ma trận nhị phân kíchthước N×M (1≤N,M≤250) Với 1 là ô bị nhiễm dầu, và 0 là ô không bị nhiễm dầu Vết dầuloang là tập hợp của một số ô bị nhiễm dầu có chung cạnh
Họ đã thuê bạn để giúp họ xử lí hình ảnh Công việc của bạn là đếm số lượng vết loangtrên biển và kích thước tương ứng của từng vết
- Dòng 1 ghi ra số lượng vết dầu loang
- Các dòng tiếp theo in ra nhiều dòng, mỗi dòng là độ lớn và số lượng vết dầu loang tương ứng với độ lớn đó theo thứ tự độ lớn vết dầu tăng dần
Trang 17Ta xây dựng một mô hình đồ thị của bài toán như sau:
Gọi mỗi đỉnh của đồ thị tương ứng với mỗi ô 1 (ô bị nhiễm dầu) của ma trận.
Tồn tại một cạnh nối giữa cặp đỉnh (u,v) khi và chỉ khi ô tương ứng với đỉnh u kề cạnhvới ô tương ứng với đỉnh v và cả hai ô đều là ô 1
Khi đó, bài toán quy về thành bài toán xác định thành phần liên thông của đồ thị.
Trong đó, mỗi thành phần liên thông tương ứng với mỗi một vết dầu loang
Nghĩa là, số lượng thành phần liên thông của đồ thị chính là số lượng vết dầu loang Và
số lượng đỉnh nằm trong cùng một thành phần liên thông là kích thước của vết loang tươngứng
Thuật toán
Áp dụng thuật toán loang trên ma trận để xác định thành phần liên thông:
Khởi tạo số lượng vết dầu bằng 0
Duyệt dần từng ô của ma trận, nếu ô đang xét là một ô bị nhiễm dầu (ô 1) và chưa được đánh dấu:
o Đánh dấu lại ô đó
o Tăng số lượng vết dầu thêm 1
o Thực hiện thủ tục BFS xuất phát từ ô đó để loang ra các ô xung quanh như sau:
Khởi tạo kích thước của vết dầu đang xét là 1
Tiếp tục thực hiện công việc sau cho đến khi không còn thực hiện đượcnữa: Từ một ô đã đánh dấu, ta đánh dấu tất cả các ô bị nhiễm dầu kề cạnh với ô đó mà chưa được đánh dấu Mỗi lần đánh dấu lại một ô thì
ta tăng kích thước của vết dầu thêm 1
Sử dụng 1 mảng để lưu lại kích thước của từng vết loang
Nếu tất cả các ô bị nhiễm dầu đều đã được đánh dấu, trả ra kết quả và kết thúc thuật toán
Mô tả