Cơ sở toán học của một số bài toán tin học

24
1 MC LC I. PHẦN ĐẶT VẤN ĐỀ: .............................................................................................. 2 I.1/ Lý do chọn đề tài ................................................................................................... 2 I.2/ Mục tiêu nghiên cứu .............................................................................................. 2 I.3/ Nhiệm vụ nghiên cứu............................................................................................. 2 I.4/ Đối tượng nghiên cứu ............................................................................................ 2 I.5/ Các phương pháp nghiên cứu................................................................................. 2 II/. PHẦN NỘI DUNG:................................................................................................. 3 II.1/ Lịch sử của vấn đề nghiên cứu ............................................................................. 3 II.2/ Cơ sở lý luận của đề tài ........................................................................................ 3 II.3/ Thực trạng của vấn đề nghiên cứu ........................................................................ 3 II.4/ Nội dung nghiên cứu và kết quả nghiên cứu ......................................................... 3 A/ NỘI DUNG NGHIÊN CỨU ................................................................................... 3 1. MỘT SỐ KHÁI NIỆM CƠ BẢN ............................................................................. 3 1.1. Đồ thị................................................................................................................. 3 1.2. Biểu diễn đồ thị.................................................................................................. 6 2. PHƯƠNG PHÁP TÌM KIẾM TRÊN ĐỒ THỊ ....................................................... 11 2.1. Một số khái niệm ............................................................................................. 11 2.2. Hai thuật toán tìm kiếm trên đồ thị ................................................................... 13 3. MỘT SỐ BÀI TẬP ÁP DỤNG: ............................................................................. 15 B/ KẾT QUẢ NGHIÊN CỨU .................................................................................... 23 III. PHẦN KẾT LUẬN ............................................................................................... 24 III.1/ Kết luận ............................................................................................................ 24 III.2/Tài liệu tham khảo ............................................................................................. 24

description

Giới thiệu một số kiến thức toán áp dụng trong tin học

Transcript of Cơ sở toán học của một số bài toán tin học

Page 1: Cơ sở toán học của một số bài toán tin học

1

MMỤỤCC LLỤỤCC

I. PHẦN ĐẶT VẤN ĐỀ: .............................................................................................. 2

I.1/ Lý do chọn đề tài ...................................................................................................2

I.2/ Mục tiêu nghiên cứu .............................................................................................. 2

I.3/ Nhiệm vụ nghiên cứu............................................................................................. 2

I.4/ Đối tượng nghiên cứu ............................................................................................ 2

I.5/ Các phương pháp nghiên cứu................................................................................. 2

II/. PHẦN NỘI DUNG:................................................................................................. 3

II.1/ Lịch sử của vấn đề nghiên cứu .............................................................................3

II.2/ Cơ sở lý luận của đề tài ........................................................................................ 3

II.3/ Thực trạng của vấn đề nghiên cứu ........................................................................3

II.4/ Nội dung nghiên cứu và kết quả nghiên cứu ......................................................... 3

A/ NỘI DUNG NGHIÊN CỨU ................................................................................... 3

1. MỘT SỐ KHÁI NIỆM CƠ BẢN .............................................................................3

1.1. Đồ thị................................................................................................................. 3

1.2. Biểu diễn đồ thị..................................................................................................6

2. PHƯƠNG PHÁP TÌM KIẾM TRÊN ĐỒ THỊ ....................................................... 11

2.1. Một số khái niệm ............................................................................................. 11

2.2. Hai thuật toán tìm kiếm trên đồ thị................................................................... 13

3. MỘT SỐ BÀI TẬP ÁP DỤNG: ............................................................................. 15

B/ KẾT QUẢ NGHIÊN CỨU.................................................................................... 23

III. PHẦN KẾT LUẬN ............................................................................................... 24

III.1/ Kết luận ............................................................................................................ 24

III.2/Tài liệu tham khảo ............................................................................................. 24

Page 2: Cơ sở toán học của một số bài toán tin học

2

I. PHẦN ĐẶT VẤN ĐỀ:

I.1/ Lý do chọn đề tài

Để hệ thống lại các chuyên đề bồi dưỡng HSG chuyên Tin học mà tôi đã dạy trong nhiều năm qua, đồng thời qua quá trình nghiên cứu, giảng dạy, tham khảo ý kiến đồng nghiệp, tôi thấy rằng một số bài toán tin học ứng dụng và một số bài toán trong các kỳ thi học sinh giỏi Tin học có thể ứng dụng lý thuyết đồ thị để giải quyết. Chính vì vậy tôi chọn viết đề tài về chuyên đề “CƠ SỞ TOÁN HỌC CỦA MỘT SỐ BÀI TOÁN TRONG LÝ THUYẾT ĐỒ THỊ” (Phần 1: Duyệt đồ thị cơ bản).

I.2/ Mục tiêu nghiên cứu

Như đã biết, toán học có ảnh hưởng rất lớn đến mọi lĩnh vực của cuộc sống. Các bài toán tin nếu có được thuật toán dựa trên cơ sở lý thuyết toán học vững chắc sẽ đem lại kết quả tốt hơn rất nhiều so với các thuật toán khác. Giúp các em học sinh có kiến thức tốt, tư duy tốt về lập trình; cơ sở toán học cho lý thuyết đồ thị là một trong những vấn đề mà bất cứ người lập trình tin học đều cần phải nắm vững.

I.3/ Nhiệm vụ nghiên cứu

Trước hết là thực hiện đổi mới phương pháp giảng dạy Tin học làm cho học sinh sáng tạo tìm những kết quả, lời giải hay trên một số “dạng bài toán tin có vận dụng cơ sở toán học”; giúp bản thân nắm vững hơn nữa về cơ sở toán học, tư duy thuật toán, khả năng lập trình, đồng thời trao đổi và học tập kinh nghiệm ở Quý Thầy Cô ở Tổ Tin học.

I.4/ Đối tượng nghiên cứu

Trong nghiên cứu này, các học sinh được chọn là các em học lớp chuyên Tin học khối 10, 11, 12; các học sinh được bồi dưỡng trong đội tuyển dự thi HSG cấp tỉnh, cấp quốc gia và một số giáo viên đứng lớp dạy tin học ở trường THPT Chuyên Tiền Giang.

I.5/ Các phương pháp nghiên cứu

* Phương pháp suy luận, tổng hợp: kết hợp từ nhiều nguồn tài liệu tham khảo của các tác giả và tra cứu trên mạng internet với các đề thi Học sinh Giỏi rút ra những kinh nghiệm, hệ thống lại kiến thức, mở ra các hướng mới.

* Phương pháp trò chuyện – phỏng vấn: trao đổi tâm tình với nhiều học sinh giỏi để nắm tình hình trong việc giải các bài toán tin về lý thuyết đồ thị.

* Phương pháp khảo sát: bản thân được tham gia giảng dạy các lớp, đội tuyển HSG, các kỳ tập huấn, ra đề; tham khảo đồng nghiệp, quý Thầy Cô đã giảng dạy đội tuyển nhiều năm nên có nắm được tình hình sử dụng các phương pháp làm bài của các em học sinh.

Page 3: Cơ sở toán học của một số bài toán tin học

3

* Phương pháp phân tích lý luận: phân tích giúp học sinh nắm thật rõ bản chất vấn đề, lựa chọn được phương pháp giải cho phù hợp. II/. PHẦN NỘI DUNG: II.1/ Lịch sử của vấn đề nghiên cứu

Trong những năm liên tiếp dạy bồi dưỡng HSG môn Tin Học lớp 10, 11, 12 và đội tuyển dự thi HSG cấp Tỉnh, cấp Quốc Gia, đội tuyển dự thi Olympic 30/4 dành cho các trường THPT, cũng như tham khảo ý kiến các đồng nghiệp chuyên dạy bồi dưỡng đội tuyển ở các Tỉnh bạn, ở các trường THPT Chuyên, tôi rút ra một điều là “CƠ SỞ TOÁN HỌC RẤT QUAN TRỌNG TRONG DẠY LẬP TRÌNH”. Được sự động viên khuyến khích của quý Thầy Cô trong tổ, tôi mạnh dạng chọn viết đề tài “Cơ sở toán học của một số bài toán trong lý thuyết đồ thị”.

II.2/ Cơ sở lý luận của đề tài

Kết hợp các bài giảng và tài liệu tham khảo, kinh nghiệm bản thân để phân tích, tổng hợp, hệ thống lại.

II.3/ Thực trạng của vấn đề nghiên cứu

Đa số học sinh chuyên tin rất ngại, sợ khi giải các bài toán tin có ứng dụng toán học; rất lúng túng trong quá trình phân tích, tổ chức dữ liệu để tìm ra bản chất và vận dụng kiến thức một cách thích hợp, tìm thuật toán tối ưu.

II.4/ Nội dung nghiên cứu và kết quả nghiên cứu

A/ NỘI DUNG NGHIÊN CỨU 1. MỘT SỐ KHÁI NIỆM CƠ BẢN

1.1. Đồ thị

1.1.1. Định nghĩa đồ thị: Là một cấu trúc rời rạc gồm các đỉnh và các cạnh nối các đỉnh đó. Được mô tả

hình thức: G = (V, E), trong đó V gọi là tập các đỉnh (Vertices) và E gọi là tập các cạnh (Edges). Có thể coi E là tập các cặp (u, v) với u và v là hai đỉnh của V. Một số hình ảnh của đồ thị:

Sơ đồ giao thông Mạng máy tính

Hình 1.1. Ví dụ về mô hình đồ thị

Page 4: Cơ sở toán học của một số bài toán tin học

4

1.1.2. Một số khái niệm Như trên định nghĩa đồ thị G = (V, E) là một cấu trúc rời rạc, tức là các tập V và

E hoặc là tập hữu hạn, hoặc là tập đếm được, có nghĩa là ta có thể đánh số thứ tự 1, 2, 3, ... cho các phần tử của tập V và E. Hơn nữa, đứng trên phương diện người lập trình cho máy tính thì ta chỉ quan tâm đến các đồ thị hữu hạn (V và E là tập hữu hạn) mà thôi, chính vì vậy từ đây về sau, nếu không chú thích gì thêm thì khi nói tới đồ thị, ta hiểu rằng đó là đồ thị hữu hạn.

Các phần tử thuộc tập V gọi là đỉnh của đồ thị G. Cho hai đỉnh u, v V, nếu e = (u, v) E là cặp sắp thứ tự thì e được gọi là một

cung của đồ thị, hoặc nếu e là cặp không sắp thứ tự thì e được gọi là một cạnh của đồ thị. Khi e = (u, v) là cung thì u là đỉnh đầu của cung, v là đỉnh cuối của cung e. Khi e = (u, v) là cạnh thì u và v gọi là hai đỉnh kề của cạnh e hoặc hai đỉnh liên

thuộc e. Hai đỉnh u và v (u ≠ v) của đồ thị được gọi là hai đỉnh kề nhau nếu chúng là 2

đầu của một cạnh hoặc một cung. Hai cạnh a, b (hoặc hai cung a, b) gọi là hai cạnh kề nhau (hoặc hai cung kề

nhau) nếu chúng có một đỉnh chung. Khuyên là cạnh (hoặc cung) có 2 đầu trùng nhau. Đỉnh treo là đỉnh thuộc duy nhất một cạnh hoặc cung. Đỉnh cô lập là đỉnh không thuộc cạnh hoặc cung nào.

1.1.3. Phân loại đồ thị Cho đồ thị G = (V, E), nếu E chỉ gồm các cạnh thì G là đồ thị vô hướng. Nếu E

chỉ gồm các cung thì G là đồ thị có hướng. Nếu E gồm cả cạnh và cung thì G là đồ thị hỗn hợp.

Đa đồ thị: Đồ thị G = (V, E) vô hướng (hoặc có hướng) là đa đồ thị khi và chỉ khi nó là đồ thị không khuyên và có ít nhất một cặp đỉnh được nối với nhau bằng ít nhất 2 cạnh (hoặc 2 cung nối theo thứ tự của cặp đỉnh).

Đơn đồ thị: Đồ thị G = (V, E) vô hướng (hoặc có hướng) là đơn đồ thị khi và chỉ khi nó là đồ thị không khuyên và mỗi cặp đỉnh được nối với nhau không quá một cạnh (hoặc cung).

Vô hướng Có hướng Vô hướng Có hướng

Đơn đồ thị Đa đồ thị Hình 1.2. Phân loại đồ thị

Page 5: Cơ sở toán học của một số bài toán tin học

5

1.1.4. Bậc của đỉnh: 1.1.4.1. Định nghĩa: Bậc của đỉnh v trong đồ thị G = (V, E), ký hiệu deg(v), là số

các cạnh liên thuộc với nó, riêng khuyên tại một đỉnh được tính hai lần cho bậc của nó. Đỉnh v gọi là đỉnh treo nếu deg(v) = 1 và gọi là đỉnh cô lập nếu deg(v) = 0.

Hình 1.3

deg(v1) = 7 deg(v2) = 5

deg(v3) = 3 deg(v4) = 0

Deg(v5) = 4 deg(v6) = 1

deg(v7) = 2

Đỉnh v4 là đỉnh cô lập và đỉnh v6 là đỉnh treo.

1.1.4.2. Mệnh đề: Cho đồ thị G = (V, E). Khi đó: 2|E| = deg( )v V

v .

Chứng minh: Rõ ràng mỗi cạnh e = (u, v) được tính một lần trong deg(u) và một lần trong deg(v). Từ đó suy ra tổng tất cả các bậc của các đỉnh bằng hai lần số cạnh.

1.1.4.3. Hệ quả: Số đỉnh bậc lẻ của một đồ thị là một số chẵn. Chứng minh: Gọi V1 và V2 tương ứng là tập các đỉnh bậc chẵn và tập các đỉnh

bậc lẻ của đồ thị G = (V, E). Khi đó: 1 2

2|E| = deg( ) deg( )v V v V

v v

Vế trái là một số chẵn và tổng thứ nhất cũng là một số chẵn nên tổng thứ hai là

một số chẵn. Vì deg(v) là lẻ với mọi v V2 nên |V2| là một số chẵn.

1.1.4.4. Mệnh đề: Trong một đơn đồ thị, luôn tồn tại hai đỉnh có cùng bậc. Chứng minh: Xét đơn đồ thị G = (V, E) có |V| = n. Bậc của mỗi đỉnh trong đồ

thị có n đỉnh nhận các giá trị từ 0 đến n – 1. Rõ ràng trong đồ thị không thể đồng thời có: một đỉnh có bậc 0 (đỉnh cô lập) và một đỉnh có bậc n – 1 (có cạnh nối với tất cả các đỉnh còn lại). Vì vậy theo bậc của các đỉnh, ta chỉ có thể phân n đỉnh thành n – 1 nhóm. Vậy theo nguyên lý Dirichlet tồn tại một nhóm có ít nhất 2 đỉnh, tức là luôn tìm được ít nhất 2 đỉnh có bậc bằng nhau.

1.1.4.5. Định nghĩa: Đỉnh u được gọi là nối tới v hay v được gọi là được nối từ u trong đồ thị có hướng G nếu (u, v) là một cung của G. Đỉnh u gọi là đỉnh đầu và đỉnh v gọi là đỉnh cuối của cung này.

1.1.4.6. Định nghĩa: Bậc vào (tương ứng bậc ra) của đỉnh v trong đồ thị có hướng G, ký hiệu degt(v) (tương ứng dego(v)), là số các cung có đỉnh cuối là v.

Page 6: Cơ sở toán học của một số bài toán tin học

6

Hình 1.4

degt(v1) = 2, dego(v1) = 3 degt(v2) = 5, dego(v2) = 1

degt(v3) = 2, dego(v3) = 4 degt(v4) = 1, deg0(v4) = 3

degt(v5) = 1, dego(v5) = 0 degt(v6) = 0, dego(v6) = 0

Đỉnh có bậc vào và bậc ra cùng bằng 0 gọi là đỉnh cô lập. Đỉnh có bậc vào bằng 1 và bậc ra bằng 0 gọi là đỉnh treo, cung có đỉnh cuối là đỉnh treo gọi là cung treo.

1.1.4.7. Mệnh đề: Cho G =(V, E) là một đồ thị có hướng. Khi đó deg ( ) deg ( ) = |E|t o

v V v Vv v

.

Chứng minh: Kết quả có ngay là vì mỗi cung được tính một lần cho đỉnh đầu và một lần cho đỉnh cuối.

1.2. Biểu diễn đồ thị

1.2.1. Biểu diễn bằng hình học Biểu diễn đỉnh: mỗi đỉnh tương ứng một điểm ghi trên mặt phẳng hoặc không

gian. Dùng kí hiệu, tên hoặc số hiệu của đỉnh ghi bên điểm tương ứng. Biểu diễn cạnh (cung): Nếu e = (u, v) là một cạnh thì nối điểm u với điểm v bằng

một đoạn thẳng hoặc đoạn cong không đi qua các điểm biểu diễn đỉnh khác. Nếu e = (u, v) là một cung thì nối từ điểm u tới điểm v bằng một đoạn thẳng định

hướng hoặc đoạn cong định hướng (có chiều mũi tên từ u tới v) không đi qua các điểm biểu diễn các đỉnh khác.

Hình nhận được gọi là dạng biểu diễn hình học của đồ thị. Để thuận tiện người ta cũng gọi dạng biểu diễn hình học của đồ thị là đồ thị.

Hình 1.5. Đơn đồ thị, vô hướng

Hình 1.6. Đa đồ thị, vô hướng

Page 7: Cơ sở toán học của một số bài toán tin học

7

Hình 1.7. Đa đồ thị, có hướng

1.2.2. Biểu diễn đồ thị trên máy tính 1.2.2.1. Biểu diễn đồ thị bằng ma trận liền kề (ma trận liền kề)

Giả sử đồ thị G = (V, E) có tập đỉnh V = {u1, u2, …, un}, tập cạnh (hoặc cung) là

E. Ta xây dựng ma trận vuông A cấp n sao cho i, j: 1 ≤ i, j ≤ n có:

ExxkhiExxkhi

jiAji

ji

,1,0

,

Ma trận A gọi là ma trận liên thuộc (ma trận kề). Ví dụ:

Hình 1.8

1 2 3 4 5 1 0 0 1 1 0 2 0 0 0 1 1 3 1 0 0 0 1 4 1 1 0 0 0 5 0 1 1 0 0

[

Hình 1.9

1 2 3 4 5 1 0 0 1 0 0 2 0 0 0 1 0 3 0 0 0 0 1 4 1 0 0 0 0 5 0 1 0 0 0

Nhận xét: - Nếu G là đồ thị vô hướng thì ma trận A sẽ đối xứng qua đường chéo chính,

ij jiA A | i, j :1 i, j n . Tổng các số trên hàng i = Tổng các số trên cột i = Bậc của

đỉnh i = deg(i) - Nếu G là đồ thị có hướng, A là ma trận liền kề tương ứng thì trên ma trận A

Tổng các số trên hàng i = Bán bậc ra của đỉnh i = degt(i) Tổng các số trên cột i = Bán bậc vào của đỉnh i = dego(i)

Page 8: Cơ sở toán học của một số bài toán tin học

8

Trong trường hợp G là đơn đồ thị, ta có thể biểu diễn ma trận liền kề A tương ứng

là các phần tử logic. Aij = TRUE nếu (i, j) E và Aij = FALSE nếu (i, j) E.

Ưu điểm của ma trận liền kề:

Đơn giản, trực quan, dễ cài đặt trên máy tính.

Để kiểm tra xem hai đỉnh (u, v) của đồ thị có kề nhau hay không, ta chỉ việc kiểm tra bằng một phép so sánh: Auv ≠ 0.

Nhược điểm của ma trận liền kề:

Bất kể số cạnh của đồ thị là nhiều hay ít, ma trận liền kề luôn luôn đòi hỏi n2 ô nhớ để lưu các phần tử ma trận, điều đó gây lãng phí bộ nhớ dẫn tới việc không thể biểu diễn được đồ thị với số đỉnh lớn.

Với một đỉnh u bất kỳ của đồ thị, nhiều khi ta phải xét tất cả các đỉnh v khác kề với nó, hoặc xét tất cả các cạnh liên thuộc với nó. Trên ma trận liền kề việc đó được thực hiện bằng cách xét tất cả các đỉnh v và kiểm tra điều kiện Auv ≠0. Như vậy, ngay cả khi đỉnh u là đỉnh cô lập (không kề với đỉnh nào) hoặc đỉnh treo (chỉ kề với 1 đỉnh) ta cũng buộc phải xét tất cả các đỉnh và kiểm tra điều kiện trên dẫn tới lãng phí thời gian.

1.2.2.2. Biểu diễn bằng ma trận trọng số Trong nhiều bài toán về đồ thị, mỗi cạnh (hoặc cung) e = (ui, uj) của đồ thị

thường được gắn với một số c(e) gọi là trọng số của cạnh (hoặc cung) e. Khi đó thường xây dựng ma trận vuông cấp n là ma trận C có mỗi phần tử C[i, j] = c(e) nếu tồn tại cạnh (hoặc cung) e = (ui, uj) ngược lại khi không có cạnh nối ui với uj (hoặc không có cung nào

nối trực tiếp ui tới uj) thì C[i, j] = (kí hiệu là giá trị không xác định). Trong nhiều

trường hợp, ngầm định C[i, i] = 0 với mọi đỉnh trong đồ thị không khuyên.

Hình 1.10

1 2 3 4 5 1 0 0 15 20 0 2 0 0 0 29 12 3 15 0 0 0 11 4 20 29 0 0 0 5 0 12 11 0 0

Page 9: Cơ sở toán học của một số bài toán tin học

9

1.2.2.3. Biểu diễn bằng danh sách cạnh Để có danh sách cạnh/cung của đồ thị G = (V, E), người

ta liệt kê và lưu tất cả các cạnh/cung của đồ thị. Trong cách biểu diễn này, người ta liệt kê tất cả các cạnh của đồ thị trong một danh sách, mỗi phần tử của danh sách là một cặp (u, v) tương ứng với một cạnh của đồ thị. (Trong trường hợp đồ thị có hướng thì mỗi cặp (u, v) tương ứng với một cung, u là đỉnh đầu và v là đỉnh cuối của cung). Danh sách được lưu trong bộ nhớ dưới dạng mảng hoặc danh sách móc nối. Ví dụ với đồ thị bên:

Hình 1.11

Cài đặt trên mảng:

1 2 3 4 5 (1, 3) (2, 4) (3, 5) (4, 1) (5, 2)

Cài đặt trên danh sách móc nối:

Ưu điểm của danh sách cạnh:

Trong trường hợp đồ thị thưa (có số cạnh tương đối nhỏ: chẳng hạn m < 6n), cách biểu diễn bằng danh sách cạnh sẽ tiết kiệm được không gian lưu trữ, bởi nó chỉ cần 2m ô nhớ để lưu danh sách cạnh.

Trong một số trường hợp, ta phải xét tất cả các cạnh của đồ thị thì cài đặt trên danh sách cạnh làm cho việc duyệt các cạnh dễ dàng hơn. (Thuật toán Kruskal chẳng hạn)

Nhược điểm của danh sách cạnh: Nhược điểm cơ bản của danh sách cạnh là khi ta cần duyệt tất cả các đỉnh kề

với đỉnh v nào đó của đồ thị, thì chẳng có cách nào khác là phải duyệt tất cả các cạnh, lọc ra những cạnh có chứa đỉnh v và xét đỉnh còn lại. Điều đó khá tốn thời gian trong trường hợp đồ thị dày (nhiều cạnh).

1.2.2.4. Biểu diễn bằng danh sách kề Cho đồ thị G = (V, E), với mỗi đỉnh ui V ta lưu trữ tất cả các đỉnh kề với nó

vào một danh sách, hình thành danh sách kề. Thường dùng 2 cách sau tạo danh sách kề:

1.2.2.4.1. Dùng các danh sách móc nối: Với mỗi đỉnh ui V ta lưu trữ tất cả các đỉnh kề với nó bằng một danh sách liên

kết một chiều, có nghĩa là tương ứng với một đỉnh ui, ta phải lưu lại List[ui] là chốt của một danh sách móc nối. Tập hợp các danh sách liên kết một chiều của các đỉnh gọi là danh sách kề của đồ thị.

Ví dụ với đồ thị hình 1.12, danh sách móc nối sẽ là:

Page 10: Cơ sở toán học của một số bài toán tin học

10

Hình 1.12

1.2.2.4.2. Dùng cách tổ chức danh sách kề theo kiểu Forward Star.

Mảng đó chia làm n đoạn, đoạn thứ i trong mảng lưu danh sách các đỉnh kề với đỉnh i: với đồ thị hình 1.13, danh sách kề sẽ là một mảng A gồm 12 phần tử:

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

2 3 5 1 3 1 2 4 3 5 1 4

Đoạn 1 Đoạn 2 Đoạn 3 Đoạn 4 Đoạn 5 Hình 1.13

Xây dựng 2 mảng một chiều A và P với ý nghĩa sau: Các vị trí j trong mảng A từ P[i-1]+1 đến P[i] cho biết A[j] là đỉnh kề với đỉnh i.

Ví dụ: Với đồ thị như hình 1.13 có số đỉnh là N = 5, số cạnh là M = 6 Mảng A 1..2*M = 2, 3, 5, 1, 3, 1, 2, 4, 3, 5, 1, 4

Mảng P 0.. N = 0, 3, 5, 8, 10, 12

Dựa vào hai mảng A và P có thể biết các đỉnh kề với đỉnh 3 là các đỉnh từ vị trí p[2]+1 = 5 + 1 = 6 tới vị trí p[3] = 8 trong mảng A; đó là các đỉnh A[6] = 1, A[7] = 2 và A[8] = 4.

Lưu ý rằng với đồ thị có hướng gồm m cung thì cấu trúc Forward Star cần phải đủ chứa m phần tử, với đồ thị vô hướng m cạnh thì cấu trúc Forward Star cần phải đủ chứa 2m phần tử. Ưu điểm của danh sách kề:

Đối với danh sách kề, việc duyệt tất cả các đỉnh kề với một đỉnh v cho trước là hết sức dễ dàng, cái tên “danh sách kề” đã cho thấy rõ điều này. Việc duyệt tất cả các cạnh cũng đơn giản vì một cạnh thực ra là nối một đỉnh với một đỉnh khác kề nó.

Nhược điểm của danh sách kề: Về lý thuyết, so với hai phương pháp biểu diễn trên, danh sách kề tốt hơn hẳn.

Chỉ có điều, trong trường hợp cụ thể mà ma trận kề hay danh sách cạnh không thể hiện nhược điểm thì ta nên dùng ma trận kề (hay danh sách cạnh) bởi cài đặt danh sách kề có phần dài dòng hơn.

Page 11: Cơ sở toán học của một số bài toán tin học

11

2. PHƯƠNG PHÁP TÌM KIẾM TRÊN ĐỒ THỊ

2.1. Một số khái niệm

2.1.1. Định nghĩa 1. Đường đi có độ dài k (k nguyên dương) từ đỉnh u đến đỉnh v trên đồ thị vô hướng G = (V, E) là dãy các đỉnh 0 1 2, , ,..., ku u u u u v mà các cạnh

1( , ) , 0, 1i iu u E i k . Đường đi này còn có thể biểu diễn dưới dạng dãy các cạnh:

0 1 1 2 1( , ), ( , ),..., ( , )k ku u u u u u . Đỉnh u gọi là đỉnh đầu (định xuất phát), đỉnh v gọi là đỉnh cuối (đỉnh đích) của đường đi.

2.1.2. Định nghĩa 2. Đường đi có độ dài k (k nguyên dương) từ đỉnh u đến đỉnh v trên đồ thị có hướng G = (V, E) là dãy các đỉnh 0 1 2, , ,..., ku u u u u v mà các cung

1( , ) , 0, 1i iu u E i k . Đường đi này còn có thể biểu diễn dưới dạng dãy các cung:

0 1 1 2 1( , ), ( , ),..., ( , )k ku u u u u u . Đỉnh u gọi là đỉnh đầu, đỉnh v gọi là đỉnh cuối của đường đi. 2.1.3. Định nghĩa 3. Đường đi có đỉnh đầu trùng với đỉnh cuối gọi là một chu trình

(mạch vòng). Đường đi hay chu trình được gọi là đơn nếu không có cung nào bị lặp lại. Đường đi hay chu trình được gọi là cơ bản nếu không có đỉnh nào bị lặp lại (trừ

trường hợp trong chu trình thì đỉnh đầu trùng đỉnh cuối là được lặp lại). 2.1.4. Định nghĩa 4. Đồ 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ó. 2.1.5. Định nghĩa 5. Cho đồ thị vô hướng G = (V, E) và đồ thị con của G là đồ thị

' ( ', ')G V E . Đồ thị G’ được gọi là một vùng liên thông (hoặc thành phần liên thông) của G nếu:

+ G’ liên thông; + Không tồn tại đường đi nào từ một đỉnh thuộc G’ tới một đỉnh không thuộc G’

(nói cách khác là bảo đảm tính tối đại của liên thông trong G’). Ví dụ. Trong hình 2.1 xét hai đồ thị là G và H: G chỉ có một vùng liên thông duy

nhất, H có 3 vùng liên thông là H1, H2, H3.

Hình 2.1. G liên thông, H gồm 3 vùng liên thông

2.1.6. Định nghĩa 6. Đỉnh v được gọi là đỉnh khớp (đỉnh rẽ nhánh) của đồ thị vô hướng G = (V, E) nếu khi loại bỏ đỉnh v và các cạnh liên thuộc với nó thì số thành phần liên thông của G tăng thêm.

Page 12: Cơ sở toán học của một số bài toán tin học

12

Cạnh e E được gọi là cầu nếu loại bỏ nó khỏi đồ thị G thì số thành phần liên thông của G tăng thêm 1 đơn vị.

2.1.7. Định nghĩa 7. Đồ thị có hướng G = (V, E) được gọi là liên thông mạnh nếu với mọi cặp đỉnh có thứ tự tuỳ ý luôn tìm được đường đi có hướng từ đỉnh thứ nhất đến đỉnh thứ hai. Nói cách khác, với mọi cặp đỉnh u và v luôn tồn tại hai đường đi: đường đi có hướng từ đỉnh u đến đỉnh v và đường đi có hướng từ đỉnh v đến đỉnh u.

2.1.8. Định nghĩa 8. Đồ thị có hướng G = (V, E) được gọi là liên thông yếu nếu khi coi các cung đều là cạnh thì được đồ thị vô hướng tương ứng là liên thông.

Hiển nhiên, đồ thị liên thông mạnh cũng liên thông yếu nhưng điều ngược lại chưa đúng.

Hình 2.2. G liên thông mạnh, H liên thông yếu và không liên thông mạnh.

2.1.9. Mệnh đề: Mọi đơn đồ thị n đỉnh (n 2) có tổng bậc của hai đỉnh tuỳ ý không nhỏ hơn n đều là đồ thị liên thông.

Chứng minh: Cho đơn đồ thị G = (V, E) có n đỉnh (n 2) và thoả mãn yêu cầu của bài toán. Giả sử G không liên thông, tức là tồn tại hai đỉnh u và v sao cho không có đường đi nào nối u và v. Khi đó trong đồ thị G tồn tại hai thành phần liên thông là G1 có n1 đỉnh và chứa u, G2 chứa đỉnh v và có n2 đỉnh. Vì G1, G2 là hai trong số các thành phần liên thông của G nên n1+n2 n. ta có:

1 2 1 2deg u deg v (n 1) (n 1) n n 2 n 2 n .

Điều mâu thuẫn ở trên dẫn đến kết luận là đồ thị G phải liên thông. 2.1.10. Hệ quả: Đơn đồ thị mà bậc của mỗi đỉnh của nó không nhỏ hơn một nửa số

đỉnh là đồ thị liên thông. 2.1.11. Mệnh đề: Nếu một đồ thị có đúng hai đỉnh bậc lẻ thì hai đỉnh này phải liên

thông, tức là có một đường đi nối chúng. Chứng minh: Cho G = (V, E) là đồ thị thị có đúng hai đỉnh bậc lẻ là u và v. Giả

sử u và v không liên thông với nhau. Khi đó chúng phải thuộc hai thành phần liên thông nào đó của đồ thị G, G1 chứa u và G2 chứa v.

Bậc của đỉnh u trong G1 cũng chính là bậc của u trong G, nên trong G1 đỉnh u vẫn có bậc lẻ và G1 có duy nhất một đỉnh bậc lẻ. Điều này mâu thuẫn. Vậy hai đỉnh u và v phải liên thông.

Page 13: Cơ sở toán học của một số bài toán tin học

13

2.2. Hai thuật toán tìm kiếm trên đồ thị

Có nhiều bài toán trên đồ thị yêu cầu duyệt (thăm) tất cả các đỉnh của đồ thị, mỗi đỉnh đúng một lần. Những thuật toán duyệt các đỉnh gọi là thuật toán tìm kiếm trên đồ thị. Trên đồ thị có hai thuật toán tìm kiếm cơ bản: Thuật toán tìm kiếm theo chiều sâu (DFS) và thuật toán tìm kiếm theo chiều rộng (BFS).

Trong mục này chúng ta chỉ xét đồ thị vô hướng G = (V, E) có N đỉnh và M cạnh.

2.2.1. Tìm kiếm theo chiều sâu trên đồ thị (DFS - depth first search) Cài đặt bằng đệ quy:

Tư tưởng của thuật toán có thể trình bày như sau: Trước hết, mọi đỉnh x kề với S tất nhiên sẽ đến được từ S. Với mỗi đỉnh x kề với S đó thì tất nhiên những đỉnh y kề với x cũng đến được từ S... Điều đó gợi ý cho ta viết một thủ tục đệ quy DFS(u) mô tả việc duyệt từ đỉnh u bằng cách thông báo thăm đỉnh u và tiếp tục quá trình duyệt DFS(v) với v là một đỉnh chưa thăm kề với u.

- Để không một đỉnh nào bị liệt kê tới hai lần, ta sử dụng kỹ thuật đánh dấu, mỗi lần thăm một đỉnh, ta đánh dấu đỉnh đó lại để các bước duyệt đệ quy kế tiếp không duyệt lại đỉnh đó nữa

- Để lưu lại đường đi từ đỉnh xuất phát S, trong thủ tục DFS(u), trước khi gọi đệ quy DFS(v) với v là một đỉnh kề với u mà chưa đánh dấu, ta lưu lại vết đường đi từ u tới v bằng cách đặt DD[v] := u, tức là DD[v] lưu lại đỉnh liền trước v trong đường đi từ S tới v. Khi quá trình tìm kiếm theo chiều sâu kết thúc, đường đi từ S tới F sẽ là:

1 2 1F p DD F p DD[p ] ... S .

procedure DFS(uV); begin

1. Thông báo tới được u; 2. Đánh dấu u là đã thăm (có thể tới được từ S); 3. Xét mọi đỉnh v kề với u mà chưa thăm , với mỗi đỉnh v đó

begin DD[v] := u; {Lưu vết đường đi, đỉnh mà từ đó tới v là u} DFS(v);{Gọi đệ quy duyệt tương tự đối với v}

end; end;

Begin {Chương trình chính} Nhập dữ liệu: đồ thị, đỉnh xuất phát S, đỉnh đích F; Khởi tạo: Tất cả các đỉnh đều chưa bị đánh dấu; DFS(S); Nếu F chưa bị đánh dấu thì không thể có đường đi từ S tới F; Nếu F đã bị đánh dấu thì truy theo vết để tìm đường đi từ S tới F;

End.

Page 14: Cơ sở toán học của một số bài toán tin học

14

Ví dụ: Tìm kiếm DFS trên đồ thị Hình 2.3, bắt đầu từ đỉnh 1, sẽ lần lượt thăm các đỉnh là: 1, 2, 4, 6, 5, 8, 9, 13, 15, 7, 3, 14, 12, 10, 11.

Hình 2.3 Với cây thể hiện quá trình đệ quy DFS ở trên, ta thấy nếu dây chuyền đệ quy là:

DFS(S) DFS(u1) DFS(u2) ... Thì thủ tục DFS nào gọi cuối dây chuyền sẽ được thoát ra đầu tiên, thủ tục DFS(S) gọi đầu dây chuyền sẽ được thoát cuối cùng. Vậy nên chăng, ta có thê mô tả dây chuyền đệ quy bằng một ngăn xếp (Stack).

2.2.2. Tìm kiếm theo chiều rộng BFS (Breadth first search) Cho một đồ thị G = <V, E> và một đỉnh nguồn s.

Ý tưởng: Bước 1: Xuất phát từ s, ta đi tới các đỉnh kề với đỉnh s. Bước 2: Sau khi đã thăm mọi đỉnh kề với đỉnh s, ta tới các đỉnh chưa được thăm nhưng

kể với những đỉnh vừa được thăm tại bước 1. Bước 3: Sau khi thăm các đỉnh ở bước 2, ta tới những đỉnh chưa được thăm nhưng kề với

những đỉnh vừa được thăm tại bước 2. ……

Quá trình được thực hiện cho đến khi tất cả các đỉnh có thể đến được từ đỉnh nguồn đều đã được thăm.

Ví dụ: Tìm kiếm BFS trên đồ thị Hình 2.3 bắt đầu từ đỉnh 1, sẽ lần lượt thăm các

đỉnh là: 1, 2, 4, 12, 6, 7, 10, 11, 5, 14, 3, 8, 9, 13, 15. Lưu ý:

Mỗi thủ tục DFS(S), BFS(S) sẽ cho phép thăm tất cả các đỉnh cùng một thành phần liên thông với s.

Hai thủ tục được gọi tìm kiếm từ mọi đỉnh chưa được thăm, vì vậy sẽ thăm được tất cả các đỉnh (mỗi đỉnh một lần): dù đồ thị có liên thông hay không liên thông.

Page 15: Cơ sở toán học của một số bài toán tin học

15

3. MỘT SỐ BÀI TẬP ÁP DỤNG:

3.1. Tìm đường đi giữa hai đỉnh 3.1.1. Bài toán. Giả sử s và t là hai đỉnh nào đó của đồ thị G. Hãy tìm đường đi từ s

đến t. 3.1.2. Hướng dẫn.

Như trên đã nêu, hai thủ tục DFS(s) và BFS(s) sẽ thăm tất cả các đỉnh cùng vùng liên thông với s. Do đó, sau khi thực hiện xong thủ tục mà t chưa được thăm

( dd t false ) thì không tồn tại đường đi từ s tới t. Ngược lại nếu t được thăm

( dd t true ) thì tồn tại đường đi. Để ghi nhận đường đi, có thể tổ chức thêm mảng

Trace(N) với Trace i j có nghĩa là trên đường đi có đỉnh j là đỉnh ngay trước đỉnh i.

Lần ngược tại Trace[t] sẽ tìm được đường đi. 3.1.3. Chương trình minh họa.

Chương trình minh họa bằng thuật toán DFS – đệ qui: program Depth_First_Search_Dequi; const max = 100; fi = ‘Duyet_DFS.inp’; fo = ‘Duyet_DFS.out’; var a: array[1.. max, 1.. max] of Boolean; {Ma tran ke cua do thi} Trace: array[1.. max] of Integer; {Trace[v] = w, dinh lien truoc v la w} n, X, Y: Integer; f, g: text; procedure Enter; var i, u, v, m: Integer; begin FillChar(a, SizeOf(a), False); {Khoi tao do thi chua co canh nao} Assign(f, fi); Reset(f); ReadLn(f, n, m, X, Y); for i := 1 to m do begin ReadLn(f, u, v); a[u, v] := True; a[v, u] := True; end; Close(f); end; procedure DFS(u: Integer); {Thuat toan tim kiem theo chieu sau bat dau tu dinh u} var v: Integer; begin for v := 1 to n do if (Trace[v] = 0) and a[u, v] then {Voi moi dinh v chua tham ke voi u} begin Trace[v] := u; DFS(v); {Tiep tuc tim kiem theo chieu sau bat dau tu v} end; end; procedure Result; {In duong di tu X toi Y} begin if Trace[Y] = 0 then {Neu Y chua danh dau tham tuc la khong co duong} WriteLn(g, ‘Path from ‘, X, ‘ to ‘, Y, ‘ not found’)

Page 16: Cơ sở toán học của một số bài toán tin học

16

else {Truy vet duong di, bat dau tu Y} begin while Y <> X do begin Write(g, Y, ‘ <- ‘); Y := Trace[Y]; end; WriteLn(g, X); end; end; begin Enter; Assign(g, fo); Rewrite(g); FillChar(Trace, n, 0); DFS(X); Result; Close(g); end.

3.1.4. Nhận xét.

Đường đi tìm được theo BFS(s) là đường đi qua ít đỉnh nhất (gọi là đường đi ngắn nhất) từ s đến t.

Cũng có thể áp dụng tìm đường đi có hướng trên đồ thị có hướng bằng các thủ tục BFS(s) và DFS(s).

3.2. Tìm các thành phần liên thông của đồ thị 3.2.1. Thành phần liên thông của đồ thị vô hướng a) Bài toán. Cho đồ thị vô hướng. Tìm số thành phần liên thông của đồ thị. b) Hướng dẫn

Phương pháp 1. Khi thực hiện thủ tục DFS(s) và BFS(s). Các đỉnh thăm được từ s phải cùng thuộc

một vùng liên thông với s nên tất cả các đỉnh này ghi nhận cùng một số hiệu vùng liên thông.

Chương trình minh họa: Program So_tp_lienthong; const max = 100; fi = ‘so_tp_lt.inp’; fo = ‘so_tp_lt.out’; type m1 = array[0.. max] of integer; m2 = array[1.. max, 1.. max] of 0..1; var a: m2; {ma tran ke} v: m1; {mang ghi nhan so hieu vung lien thong cua dinh} n: integer; sv: integer; {so luong vung lien thong} procedure read_inp; var f: text; i, j: integer; begin assign(f, fi); reset(f); readln(f, n); fillchar(a, sizeof(a), 0); while not seekeof(f) do {tao ma tran ke} begin

Page 17: Cơ sở toán học của một số bài toán tin học

17

read(f, i); while not seekeoln(f) do begin read(f, j); a[i, j] := 1; a[j, i] := 1; end; readln(f); end; close(f); end; procedure DFS(i: integer); var j: integer; begin for j :=1 to n do if v[j] = 0 then {dinh j chua thuoc vung lien thong nao} if a[i, j] =1 then {j ke voi i} begin v[j] := sv; {ghi nhan dinh j thuoc cung vung lien thong voi i la vung sv} DFS(j); {tim kiem tiep tu dinh j} end; end; procedure solve; var s: integer; begin fillchar(v, sizeof(v), 0); sv := 0; for s := 1 to n do if v[s] = 0 then begin inc(sv); {tao so hieu cho mot vung lien thong moi} v[s] := sv; {s la dinh dau tien thuoc vung lien thong moi} DFS(s); {tim tat ca cac dinh lien thong voi dinh s} End; End; procedure write_out; {ghi lai cac dinh thuoc tung vung lien thong} var f: text; i, j: integer; begin assign(f, fo); rewrite(f); writeln(f, sv); {so luong vung lien thong} for i := 1 to sv do begin for j := 1 to n do {ghi nhan cac dinh j thuoc vung co so hieu la i} if v[j] = i then write(f, j, ‘ ‘); writeln(f); end; close(f); end; BEGIN Read_inp; solve; write_out; END.

Hoàn toàn tương tự, nếu trong chương trình trên thay thủ tục DFS(i) bằng thủ tục BFS(i) sẽ có chương trình tìm số thành phần liên thông theo thuật toán tìm kiếm chiều rộng.

Ngoài phương pháp trên, còn dùng phương pháp hợp nhất các vùng liên thông thành một vùng liên thông lớn hơn.

Page 18: Cơ sở toán học của một số bài toán tin học

18

Phương pháp 2. Hợp nhất dần các vùng liên thông tiến hành như sau: Ban đầu coi mỗi đỉnh thuộc một vùng, số hiệu vùng của đỉnh là số hiệu của đỉnh. Thực hiện vòng lặp:

- Duyệt lần lượt các cạnh. Nếu 2 đỉnh liên thuộc một cạnh thuộc hai vùng liên thông khác nhau thì hợp nhất hai vùng liên thông này bằng cách: chọn số hiệu vùng của đỉnh có số hiệu nhỏ hơn làm số hiệu vùng chung cho các đỉnh thuộc hai vùng này.

- Lặp cho đến khi không còn hai vùng liên thông nào có thể hợp nhất với nhau.

3.2.2. Thành phần liên thông của đồ thị có hướng a) Một số nhận xét - Khi thực hiện tìm kiếm DFS trên đồ thị có hướng G sẽ hình thành cây tìm kiếm

DFS của G. Đỉnh r được gọi là một điểm chốt nếu từ các đỉnh thuộc nhánh gốc r (của cây tìm kiếm DFS trên G) không có cung nối tới một đỉnh đã thăm trước r.

- Mỗi thành phần liên thông mạnh 1G sẽ nằm hoàn toàn trong một nhánh thuộc cây tìm kiếm DFS của G, nhánh này có gốc là một điểm chốt và tập đỉnh của 1G không chứa điểm chốt nào khác.

b) Thuật toán tìm các thành phần liên thông mạnh (thuật toán Tarjan). Từ những nhận xét trên, có thuật toán Tarjan tìm các thành phần liên thông mạnh :

Bằng duyệt đệ quy (tìm kiếm DFS) thăm các đỉnh của G, tìm đỉnh chốt r, các đỉnh thuộc nhánh DFS gốc r sẽ tạo thành một thành phần liên thông mạnh. Sau đó loại bỏ thành phần này khỏi G, lặp lại quá trình trên để tìm các thành phần liên thông mạnh còn lại.

Từ định nghĩa điểm chốt, để phát hiện ra một chốt, có thể tiến hành như sau:

Dùng mảng A(N) để ghi số thứ tự thăm các đỉnh. Ví dụ A[3] = 10 có nghĩa là đỉnh có số hiệu 3 là đỉnh được thăm ngay sau 9 đỉnh khác trong quá trình tìm kiếm DFS.

Dùng mảng B(N) để theo dõi mỗi đỉnh r (của cây tìm kiếm DFS trên G) có là chốt hay không (nghĩa là không tồn tại cung nối từ một đỉnh thuộc nhánh gốc r tới một đỉnh đã thăm trước r). Để thực hiện được nhiệm vụ này, gán cho B[i] giá trị nhỏ nhất trong các giá trị A[j] mà j là đỉnh có thể tới được từ một đỉnh thuộc nhánh DFS gốc i. Cụ thể, xây dựng B[i] như sau :

+ Nếu j đã thăm thì gán B[i]mới := Min {B[i]cũ, A[j]} + Nếu j chưa thăm thì :

Gọi duyệt đệ quy thăm j, Sau đó gán B[i]mới := Min{B[i]cũ, B[j]}

Điểm i là chốt khi và chỉ khi A[i] = B[i].

3.3. Làm quen Tên chương trình: Lamquen.pas Trong một xóm có n người và giữa hai người i và j có thể đã biết nhau hoặc chưa

biết nhau. Để thắt chặt mối quan hệ giữa mọi người trong xóm, xóm trưởng quyết định

Page 19: Cơ sở toán học của một số bài toán tin học

19

như sau: Nếu một người z biết hai người người x và y mà người x chưa biết người y thì người z phải giới thiệu người x cho người y để hai người làm quen với nhau.

Ví dụ: Trong xóm có 4 người 1, 2, 3 và 4. Người 1 biết người 2, người 3. Người 2 biết người 4 thì:

Người 1 sẽ giới thiệu người 2 với người 3. Người 2 (đã biết người 3) sẽ giới thiệu người 3 với người 4. Người 2 giới thiệu người 1 với người 4.

Với cách làm như xậy, xóm trưởng muốn biết là mọi người trong xóm có biết tất cả nhau không? Dữ liệu vào gồm: Đọc từ file văn bản Lamquen.Inp có cấu trúc như sau: Dòng đầu là số n (số người trong xóm). Các dòng kế tiếp, mỗi dòng là một cặp (x, y) thể hiện cho một cặp người đã biết

nhau. Dữ liệu ra: Ghi ra file văn bản Lamquen.Out số 1 nếu tất cả mọi người trong xóm sẽ biết nhau và số 0 trong trường hợp ngược lại.

Lamquen.inp Lamquen.out 4 1 2 1 3 2 4

1

Hướng dẫn Ta coi mỗi người là một đỉnh và mỗi quan hệ là một cạnh nối giữa hai đỉnh tương

ứng với hai người. Lúc đó ta sẽ có một đồ thị G = <V, E> với V= {1, 2, ... , n} và E = {(x, y) với x, y có quan hệ}. Ví dụ với dữ liệu vào đã cho ta có đồ thị được biểu diễn trên hình 3.1.

Hình 3.1 Bài toán kiểm tra xem một người có biết những người còn lại hay không tương

đương với bài toán kiểm tra đồ thị G = <V, E> có phải là đồ thị liên thông hay không. Nếu G liên thông thì mỗi người sẽ quen với n-1 người còn lại. Nếu G không liên thông thì mỗi người sẽ không thể quen với cả n-1 người còn lại.

3.4. Miền liên thông Tên chương trình: Mien_lt.pas Cho bảng chữ nhật chia thành MxN ô vuông đơn vị (M dòng đánh số từ 1 đến M

theo chiều từ trên xuống dưới, N cột đánh số từ 1 đến N theo chiều từ trái qua phải). Mỗi ô vuông ghi một số 0 hoặc 1. Một miền 0 của bảng là tập hợp các ô chung cạnh và chứa số 0. Địa chỉ của một miền là tọa độ dòng, cột của ô đầu tiên thuộc miền theo thứ tự duyệt từ trái qua phải, từ trên xuống dưới.

Hãy tính số miền 0 của bảng và tìm miền 0 có diện tích lớn nhất. Dữ liệu vào từ file Mien_lt.inp: Dòng đầu ghi 2 số nguyên dương M và N (0 < M, N ≤ 100). M dòng tiếp theo thể hiện bảng số theo thứ tự từ trên xuống dưới, mỗi dòng N số

theo thứ tự từ trái qua phải. Kết quả ghi ra File Mien_lt.out: Dòng thứ nhất ghi số lượng miền 0.

Page 20: Cơ sở toán học của một số bài toán tin học

20

Dòng thứ hai ghi diện tích của miền 0 có diện tích lớn nhất. Các dòng tiếp theo, mỗi dòng ghi địa chỉ 1 một miền 0 có diện tích lớn nhất.

Ví dụ Mien_lt.inp Mien_lt.out

4 5 1 0 0 0 1 0 1 0 0 1 1 0 1 1 1 1 0 0 0 0

3 5 1 2 3 2

Hướng dẫn. Thực hiện vòng lặp.

1. Tìm một ô chứa số 0 chưa thăm là ô x có tọa độ dòng và cột là (i, j). 2. Loang (tìm kiếm theo chiều rộng) để tìm được miền 0 chứa ô x. Trong quá

trình loang cũng tính diện tích của miền (mỗi lần đến một ô mới thì tăng diện tích một đơn vị).

3. Mỗi lần thực hiện xong loang thì tìm được một miền 0 chứa ô (i, j), lưu kết quả (tọa độ i, j và diện tích của miền vào mảng kp) đồng thời tăng biến đếm số miền 0.

Lặp cho đến khi hết ô 0 chưa thăm. Hiện số lượng miền 0. Duyệt mảng kết để tìm miền 0 có diện tích lớn nhất. Hiện diện tích miền 0 lớn

nhất. Duyệt mảng kết lần thứ hai để hiện tọa độ từng ô đại diện cho mỗi miền 0 có

diện tích bằng diện tích của miền 0 lớn nhất. 3.5. Truyền tin trên mạng Tên chương trình: Infor.Pas

Có một nhóm gồm N lập trình viên được đánh số từ 1 tới N, một số người trong họ có biết địa chỉ email của người khác. Khi biết một thông tin mới họ gửi thông tin đó cho người mà biết. Bạn là một người rất quan trọng và bạn biết tất cả các mối quan hệ của họ cũng như bạn có một thông tin rất đặc biệt mà muốn cho tất cả họ đều biết. Hãy lập trình chỉ ra một số ít nhất các lập trình viên cần cho họ biết thông tin sao cho những người đó có thể thông báo cho tất cả những người còn lại biết thông tin của bạn. Dữ liệu cho trong file văn bản với tên Infor.inp trong đó: Dòng đầu chứa số N (N ≤ 1000). Dòng thứ i trong N dòng tiếp theo chứa danh sách các lập trình viên mà người i

biết địa chỉ email của họ. Nếu người thứ i không biết địa chỉ của bất cứ ai thì dòng này là dòng trống.

Kết quả ghi ra file văn bản với tên Infor.out trong đó: Dòng đầu ghi số K là số người cần cho họ biết thông tin. Dòng thứ hai ghi ra chỉ số của những người đó.

Ví dụ: Infor.inp Infor.out

6 2 3 1 1 5 4

3 1 4 6

Page 21: Cơ sở toán học của một số bài toán tin học

21

Hướng dẫn: Đếm số miền liên thông trong đồ thị (chú ý đồ thị có hướng)

3.6. Điều khiển Robot Tên chương trình: DK_Robot.pas Sân thi điều khiển Rô bốt là một hình chữ nhật kích thước NxM ô vuông. Một số ô

được làm trũng và chứa đầy nước. Rô bốt được đặt ở ô đánh dấu S và phải di chuyển một cách nhanh nhất về ô được đánh dấu E theo các quy tắc sau: Không được đi vào các ô có nước, Đến một ô nào đó, Rô bốt có thể đi thẳng, rẽ trái hoặc phải (nếu ô mới không chứa

nước và nằm trong sân), Rô bốt không được đi theo đường chéo hay quay ngược, Rô bốt xuất phát theo hướng tuỳ chọn và đến đích theo hướng bất kỳ. Thời gian chuyển sang ô mới là 1 đơn vị.

Yêu cầu: Xác định khoảng thời gian tối thiểu cần thiết để đưa Rô bốt về đích. Dữ liệu: Vào từ file văn bản DK_Robot.inp: Dòng đầu tiên chứa 2 số nguyên N, M (N dòng, M cột), 0 < N, M ≤ 50), N dòng sau: mỗi dòng chứa M số nguyên 0, 1, 2 hoặc 3, các số cách nhau một

dấu cách, 0 là ô được đi, 1 – ô có nước, 2 – ô xuất phát S, 3 – ô đích E. Chỉ có một ô xuất phát và một ô đích.

Kết quả: Đưa ra file văn bản DK_Robot.out thời gian tối thiểu tìm được (nguyên). Nếu không tới được thì đưa ra số -1. Ví dụ:

DK_Robot.inp DK_Robot.out 5 5 2 0 0 1 1 0 1 0 0 1 1 1 0 0 1 0 0 0 0 1 3 1 0 0 1

8

Hình 3.2 Hướng dẫn: Dùng loang theo BFS

3.7. Sói và cừu Tên chương trình: Soicuu.pas Có một số con cừu trong trại chăn nuôi của Mickey. Trong khi Mickey đang ngủ

say, những con sói đói đã vào trại và tấn công đàn cừu. Trang trại hình chữ nhật gồm các ô được tổ chức thành hàng và cột. Trên bản đồ thể

hiện trang trại có các kí hiệu: kí tự “. ” là ô rỗng, kí tự “#” là hàng rào, kí tự “o” là cừu và “v” là chó sói. Hai ô được xem là cùng môt miền nếu ta di chuyển từ ô này sang ô khác bằng đường đi theo chiều ngang hoặc dọc và không có rào cản. Các ô mà từ đó có thể thoát khỏi trang trại không được xem là một phần của bất kì miền nào.

May thay, những con cừu biết tự vệ. Chúng có thể chiến đấu với những con sói trong miền (húc chết sói) nếu số lượng của chúng lớn hơn số lượng sói trong cùng miền. Ngược lại, những con sói sẽ ăn hết các con cừu trong cùng một miền.

Ban đầu, các con cừu và sói đã được xác định trong các miền của trang trại. Viết chương trình đếm số cừu và số sói còn sống sót vào buổi sáng hôm sau đó.

Dữ liệu vào: file văn bản Soicuu.inp gồm: Dòng đầu chứa 2 số nguyên R và C, 3 ≤ R, C ≤ 250, là số dòng và số cột của trang trại. Trong R dòng tiếp theo, mỗi dòng gồm C kí tự. Tất cả các kí tự này biểu diễn các

vị trí của ô rỗng, rào cản, cừu và sói trong trang trại.

Page 22: Cơ sở toán học của một số bài toán tin học

22

Dữ liệu ra: file văn bản Soicuu.out gồm một dòng duy nhất chứa hai số, số cừu và số sói còn sống đến buổi sáng hôm sau. Thí dụ:

Soicuu.inp Soicuu.inp Soicuu.inp 6 6 . . . # . . . # # v # . # V . # . # # . o # . # . # # # . # . . . # # #

8 8 . # # # # # # . # . . o . . . # # . # # # # . # # . # v . # . # # . # . o # o # # o . # # . . # # . v . . v . # . # # # # # # .

9 12 . # # # . # # # # # . . # . o o # . . . # v # . # . . o # . # . # . # . # . . # # o # . . . # . # . # v # o # # # . # . # . . # v # . . . . # . # . . . v # v # # # # . . # # # # . # v v . o # . . . . . . . # # # # .

Soicuu.out Soicuu.out Soicuu.out 0 2 3 1 3 5 Hướng dẫn:

Dùng thuật toán tìm kiếm xác định các miền liên thông. Trong mỗi miền liên thông đếm số cừu và số sói trong đó. Nếu số cừu lớn hơn số sói thì coi như số sói còn lại trong miền này bằng 0, ngược lại số cừu còn lại trong miền này bằng 0. Khi tìm kiếm tới ô nào thì xóa ô đó bằng cách gán kí tự ‘#’ trên ô đó.

3.8. Đường đi đến số 0 Tên chương trình: Zero.pas Mỗi một số nguyên dương đều có thể biểu diễn dưới dạng tích của 2 số nguyên

dương X, Y sao cho X<=Y. Nếu như trong phân tích này ta thay X bởi X-1 còn Y bởi Y+1 thì sau khi tính tích của chúng ta thu được hoặc là một số nguyên dương mới hoặc là số 0. Ví dụ: Số 12 có 3 cách phân tích 1*12, 3*4, 2*6. Cách phân tích thứ nhất cho ta tích mới là 0: (1-1)*(12+1)=0, cách phân tích thứ hai cho ta tích mới 10: (3-1)*(4+1)=10, còn cách phân tích thứ ba cho ta 7: (2-1)*(6+1)=7. Nếu như kết quả là khác 0 ta lại lặp lại thủ tục này đối với số thu được. Rõ ràng áp dụng liên tiếp thủ tục trên, cuối cùng ta sẽ đến được số 0, không phụ thuộc vào việc ta chọn cách phân tích nào để tiếp tục. Yêu cầu: Cho trước số nguyên dương N ( 41 10N ), hãy đưa ra tất cả các số nguyên dương khác nhau có thể gặp trong việc áp dụng thủ tục đã mô tả đối với N. Dữ liệu vào: từ file văn bản Zero.inp chứa số nguyên dương N. Kết quả: Ghi ra file văn bản Zero.out : Dòng đầu tiên ghi K là số lượng số tìm được. Dòng tiếp theo chứa K số tìm được theo thứ tự tăng dần bắt đầu từ số 0.

Lưu ý: Có thể có số xuất hiện trên nhiều đường biến đổi khác nhau, nhưng nó chỉ được tính một lần trong kết quả. Thí dụ:

Zero.inp Zero.out 12 6

0 3 4 6 7 10 Hướng dẫn:

Đơn giản là sau mỗi lần phân tích thì chắc chắn kết quả mới luôn nhỏ hơn số đó. Vì vậy ta chỉ cần lưu trữ vào mảng A: [0..10000] of boolean; trong đó A[i] = True nếu nó xuất hiện trên đường đi đó, ngược lại thì A[i] = False. Bằng cách loang theo chiều sâu, chúng ta sẽ đánh dấu các số nếu nó được dùng đến, cho đến khi không thể nào loang được nữa thì dừng.

Page 23: Cơ sở toán học của một số bài toán tin học

23

3.9. Bàn cờ thế (CHESSCBG) Tên chương trình: Chess.pas Một bàn cờ thế là một bảng gồm 4 dòng, 4 cột. Mỗi thế cờ là một cách sắp xếp 8

quân cờ, hai quân khác nhau ở hai ô khác nhau. Bài toán đặt ra là cho hai thế cờ 1 và 2, hãy tìm một số ít nhất bước di chuyển quân

để chuyển từ thế 1 sang thế 2; một bước di chuyển quân là một lần chuyển một quân cờ sang ô trống kề cạnh với ô quân cờ đang đứng. Dữ liệu vào: Dữ liệu vào được cho bởi file Chess.inp: gồm 8 dòng, mỗi dòng là một xâu nhị phân độ dài 4 mà số 1/0 tương ứng với vị trí

có hoặc không có quân cờ. Bốn dòng đầu là thế cờ 1, bốn dòng sau là thế cờ 2.

Dữ liệu ra: Kết quả ghi ra ở file Chess.out như sau: Dòng thứ nhất ghi số B là số bước di chuyển. Nếu B > 0, tiếp theo là B dòng, mỗi dòng ghi bốn số X, Y, Z, T với ý nghĩa di

chuyển quân cờ từ ô [X, Y] đến ô [Z, T]. Ví dụ:

Chess.inp Chess.out 1111 0000 1110 0010 1010 0101 1010 0101

4 1 2 2 2 1 4 2 4 3 2 4 2 4 3 4 4

Hướng dẫn: Trước hết, ta có thể thấy rằng với hai thế cờ T1 và T2 bất kì cho trước ta luôn có thể

chuyển từ T1 đến T2 sau một số bước đi chuyển quân cờ. Xét đồ thị mà các đỉnh là các thế cờ, cạnh nối hai thế là một bước di chuyển một

quân cờ. Có tất cả 12870 thế cờ, đây chính là số tổ hợp chập 8 của 16. Ta mã hóa mỗi thế cờ như sau: mỗi thế cờ xem như một số nhị phân 16 bit, do đó có giá trị thập phân là một số kiểu Word, ví dụ, thế cờ thứ nhất trong file Dữ liệu là 1111000011100010, có mã hoá là số 61666. Khi đó mã hoá của các thế cờ chỉ thuộc phạm vi từ 255 đến 65300. Ta sẽ dùng kĩ thuật tìm kiếm theo chiều rộng để tìm đường đi từ thế T1 đến thế T2. B/ KẾT QUẢ NGHIÊN CỨU

Qua quá trình nghiên cứu và vận dụng đề tài chuyên đề “CƠ SƠ TOÁN HỌC CỦA MỘT SỐ BÀI TOÁN TRONG LÝ THUYẾT ĐỒ THỊ” (Phần 1: Duyệt đồ thị cơ bản), tôi nhận thấy vấn đề này giúp ích rất nhiều cho học sinh chuyên tin học trong việc học, giúp các em không còn “ngán ngại” chuyên đề này nữa, các em đã hiểu và vận dụng khá tốt những phần liên quan đến lý thuyết đồ thị ứng dụng vào tin học (như duyệt đồ thị, tìm số miền liên thông, …); một số em đã bước đầu sáng tạo được những cách giải hay, các giải mới (tuy là những bài toán còn “đơn giản”). Riêng bản thân tôi sẽ tiếp tục nghiên cứu sâu hơn nữa về chuyên đề này hy vọng sẽ “làm rõ hơn nữa” để học sinh chuyên tin thích học và đạt nhiều thành tích hơn nữa.

Page 24: Cơ sở toán học của một số bài toán tin học

24

III. PHẦN KẾT LUẬN III.1/ Kết luận

Tin học và Toán học là hai bộ môn khác biệt nhưng không độc lập với nhau. Biết vận dụng những kết quả và những suy luận, chứng minh từ toán học sẽ làm cho những bài toán tin có những giải thuật đơn giản và kết quả rất tốt.

Như vậy, Tin học đã sử dụng cơ sở Toán học rất nhiều. Đặc biệt cơ sở toán học cho lý thuyết đồ thị dựa vào các định lý, bổ đề trong toán học mà Tin học đã xây dựng được những thuật toán, giải thuật rất hữu dụng, ngày nay việc ứng dụng lý thuyết đồ thị vào nhiều dạng bài toán không còn là vấn đề khó khăn như trước đây và có những ứng dụng rộng rãi.

Tôi viết đề tài nghiên cứu nhằm mục đích cùng trao đổi với Quý Thầy Cô dạy chuyên đề bồi dưỡng học sinh giỏi Tin học về việc “hệ thống” các kiến thức, một vài kỹ năng, ứng dụng toán học vào lập trình giải quyết các bài toán tin. Vì kiến thức và thời gian còn nhiều hạn chế nên chắc rằng nghiên cứu còn có thiếu sót, tôi chân thành đón nhận sự góp ý của Quý Thầy Cô. Xin chân thành cảm ơn.

III.2/Tài liệu tham khảo

1. Đại học Huế (ebook - 2003), Giáo trình Toán rời rạc.

2. Hồ Sĩ Đàm, Đỗ Đức Đông, Lê Minh Hoàng, Nguyễn Thanh Hùng, 2009, Tài

liệu giáo khoa chuyên tin, NXB Giáo dục, quyển 1, quyển 2.

3. Hồ Sĩ Đàm, Đỗ Đức Đông, Lê Minh Hoàng, Nguyễn Thanh Hùng, 2009, Tài

liệu chuyên tin học, NXB Giáo dục, Bài tập quyển 1.

4. Lê Minh Hoàng (ebook), Bài giảng chuyên đề - Phần Lý thuyết đồ thị

5. Nguyễn Xuân My (chủ biên), Hồ Sĩ Đàm, Trần Đỗ Hùng, Lê Sĩ Quang (2002),

Một số vấn đề chọn lọc trong môn Tin học (Tập 1), NXB Giáo Dục

6. Trần Đỗ Hùng (2006), Ứng dụng lý thuyết đồ thị, NXB Giáo Dục.

7. Các đề thi HSG Olympic 30/4.

8. Các đề thi HSG ĐBSCL.

9. Các đề thi HSG Quốc gia.

10. Các đề thi HSG Quốc tế.