Tải bản đầy đủ (.pdf) (24 trang)

“CƠ SỞ TOÁN HỌC CỦA MỘT SỐ BÀI TOÁN TRONG LÝ THUYẾT ĐỒ THỊ

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (487.91 KB, 24 trang )

1
M
M


C
C


L
L


C
C


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
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.
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ị
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ị
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(v
1
) = 7

deg(v
2
) = 5
deg(v
3
) = 3
deg(v
4
) = 0
Deg(v
5
) = 4
deg(v
6
) = 1
deg(v
7
) = 2
Đỉnh v
4
là đỉnh cô lập và đỉnh v
6
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 V
1
và V
2
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  V
2
nên |V
2
| 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 deg
t
(v) (tương ứng deg
o
(v)), là số các cung có đỉnh cuối là v.
6

Hình 1.4
deg
t
(v
1
) = 2, deg
o
(v
1
) = 3
deg
t
(v
2
) = 5, deg
o
(v
2
) = 1

deg
t
(v
3
) = 2, deg
o
(v
3
) = 4
deg
t
(v
4
) = 1, deg
0
(v
4
) = 3
deg
t
(v
5
) = 1, deg
o
(v
5
) = 0
deg
t
(v

6
) = 0, deg
o
(v
6
) = 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 V
v 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
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 = {u
1
, u
2
, …, u
n
}, 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ó:
 


 









Exxkhi
Exxkhi
jiA
ji
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 ji
A 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 = deg
t
(i)
Tổng các số trên cột i = Bán bậc vào của đỉnh i = deg
o
(i)
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. A
ij
= TRUE nếu (i, j)  E và A
ij
= 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: A
uv
≠ 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 n
2
ô
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 A
uv
≠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 = (u
i
, u
j
) 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 = (u
i
, u

j
) ngược lại khi không có cạnh nối u
i
với u
j
(hoặc không có cung nào
nối trực tiếp u
i
tới u
j
) 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






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 u

i


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 u
i
 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 u
i
, ta phải lưu lại List[u
i
] 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à:
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.
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
, , , ,
k
u u u u u v
 
mà các cạnh
1
( , ) , 0, 1
i i
u 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 k
u 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
, , , ,
k
u u u u u v
 
mà các cung
1
( , ) , 0, 1
i i
u 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 k
u 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.
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à G
1

n
1
đỉnh và chứa u, G
2
chứa đỉnh v và có n
2
đỉnh. Vì G
1
, G
2
là hai trong số các thành phần
liên thông của G nên n
1
+n
2
 n. ta có:




1 2 1 2
deg 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, G
1
chứa u và G
2
chứa v.
Bậc của đỉnh u trong G
1
cũng chính là bậc của u trong G, nên trong G
1
đỉnh u
vẫn có bậc lẻ và G
1
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.


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 1
F p DD F p DD[p ] S
     
.
procedure DFS(uV);
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.


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(u
1
)  DFS(u
2
) 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.
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’)
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
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.
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
1
G
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
1
G

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]

, 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]

, 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
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.
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
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.
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 (
4
1 10
N 
), 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.
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.
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ế.

×