Upload
letruc
View
224
Download
6
Embed Size (px)
Citation preview
TRƯỜNG ðẠI HỌC SƯ PHẠM KỸ THUẬT HƯNG YÊN
KHOA CÔNG NGHỆ THÔNG TIN
BÀI TẬP
HỌC PHẦN TOÁN RỜI RẠC 2
Trình ñộ ñào tạo
Hệ ñào tạo
:
:
ðại học
Chính quy/Liên thông
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 2
LỜI NÓI ĐẦU
Có thể nói toán học rời rạc là môn tiên quyết và hiệu quả nhất ñể người học
nâng cao tư duy toán học trong phân tích, thiết kế thuật toán và rèn luyện kỹ năng
lập trình với những thuật toán phức tạp. Không những thế nó còn là “cửa ngõ” ñể
người học có thể tiếp cận với rất nhiều modul trong khoa học máy tính (như
Chương trình dịch, lý thuyết tính toán, Trí tuệ nhân tạo,...). Bài tập ñể củng cố
và nâng cao kiến thức trong môn học này
Về nội dung, bám sát với chương trình của nhà trường và hệ thống bài tập
cũng ñược biên soạn theo các chương lý thuyết. Với mỗi chương sẽ ñược chia thành
4 phần:
Phần A. Nhắc lại lý thuyết: tóm tắt các kiến thức cơ bản, các ví dụ và các
lưu ý hữu ích, các kinh nghiệm trong khi lập trình
Phần B. ðề bài tập: ñưa ra các loại bài tập khác nhau, với các mức ñộ khác
nhau.
Phần C. Bài tập mẫu: Hướng dẫn giải một số bài tiêu biểu trong phần B, có
phân tích thuật toán và cài ñặt chương trình.
Phần D. Bài tập tự giải: Người học thực hiện việc giải các bài tập này
Mong rằng tài liệu này ñáp ứng ñược phần nào nhu cầu của học sinh, sinh viên. ðây
là bản ñầu tiên chắc chắn còn rất nhiều sai sót. Nhóm tác giả mong nhận ñược sự
ñóng góp của các thầy cô giáo, các bạn sinh viên và của tất cả những ai quan tâm tới
lĩnh vực này.
Hưng Yên, tháng 7 năm 2010
Bộ môn Công nghệ phần mềm
Khoa Công nghệ thông tin
Trường ñại học sư phạm kỹ thuật Hưng Yên
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 3
MỤC LỤC Bài 1: Các khái niệm cơ bản của Lý thuyết ñồ thị ............................................................5
Mục tiêu ...................................................................................................................5 a. Nhắc lại lý thuyết ..................................................................................................5 b. ðề bài tập..............................................................................................................5 c. Hướng dẫn giải......................................................................................................6 d. Bài tập tự giải .......................................................................................................7
Bài 2: Biểu diễn ñồ thị trên máy tính..............................................................................10 Mục tiêu .................................................................................................................10 a. Nhắc lại lý thuyết ................................................................................................10 b. ðề bài tập............................................................................................................10 c. Hướng dẫn giải....................................................................................................10 d. Bài tập tự giải .....................................................................................................14
Bài 3: ðồ thị Euler .........................................................................................................15 Mục tiêu .................................................................................................................15 a. Nhắc lại lý thuyết ................................................................................................15 b. ðề bài tập............................................................................................................16 c. Hướng dẫn giải....................................................................................................16 d. Bài tập tự giải .....................................................................................................19
Bài 4: ðồ thị hamilton....................................................................................................20 Mục tiêu .................................................................................................................20 a. Nhắc lại lý thuyết ................................................................................................20 b. ðề bài tập............................................................................................................20 c. Hướng dẫn giải....................................................................................................20 d. Bài tập tự giải .....................................................................................................22
Bài 5: Thảo luận cài ñặt ñồ thị, các thuật toán liệt kê chu trình Euler và Hamilton. Thảo luận về bài tập lớn.................................................................................................23
Mục tiêu .................................................................................................................23 a. Nhắc lại lý thuyết ................................................................................................23 b. ðề bài tập............................................................................................................23 c. Hướng dẫn giải....................................................................................................23 d. Bài tập tự giải .....................................................................................................31
Bài 6 Thuật toán tìm kiếm trên ñồ thị và ứng dụng.........................................................34 Mục tiêu .................................................................................................................34 a. Nhắc lại lý thuyết ................................................................................................34 b. ðề bài tập............................................................................................................34 c. Hướng dẫn giải....................................................................................................34 d. Bài tập tự giải .....................................................................................................51
Bài 7: Cây và cây khung ................................................................................................52 Mục tiêu .................................................................................................................52 a. Nhắc lại lý thuyết ................................................................................................52 b. ðề bài tập............................................................................................................53 c. Hướng dẫn giải....................................................................................................54 d. Bài tập tự giải .....................................................................................................55
Bài 8: Thảo luận về cài ñặt thuật toán tìm cây khung nhỏ nhất trên ñồ thị ......................58 Mục tiêu .................................................................................................................58
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 4
a. Nhắc lại lý thuyết ................................................................................................58 b. ðề bài tập............................................................................................................58 c. Hướng dẫn giải....................................................................................................58 d. Bài tập tự giải .....................................................................................................70
Bài 9, 10: Bài toán tìm ñường ñi ngắn nhất ....................................................................71 Mục tiêu .................................................................................................................71 a. Nhắc lại lý thuyết ................................................................................................71 b. ðề bài tập............................................................................................................71 c. Hướng dẫn giải....................................................................................................73 d. Bài tập tự giải .....................................................................................................92
Bài 12: Bài toán luồng cực ñại trong mạng.....................................................................97 Mục tiêu .................................................................................................................97 a. Nhắc lại lý thuyết ................................................................................................97 b. ðề bài tập............................................................................................................98 c. Hướng dẫn giải....................................................................................................99 d. Bài tập tự giải ...................................................................................................101
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 5
Bài 1: Các khái niệm cơ bản của Lý thuyết ñồ thị Mục tiêu
- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.
- Cài ñặt ñược chương trình chuyển ñổi giữa các phương pháp.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
- Hai ñỉnh x, y ñược gọi là cặp ñỉnh liên thông , nếu hoặc giữa x và y có ít nhất một
xích nối với nhau, hoặc tồn tại ít nhất một ñường ñi từ y sang x.
- ðồ thị vô hướng G(V,E) ñược gọi là ñồ thị liên thông, nếu mọi cặp ñỉnh của nó
ñều liên thông.
- ðồ thị có hướng G(V,E) ñược gọi là ñồ thị liên thông mạch, nếu mọi cặp ñỉnh của
nó ñều liên thông.
- Biểu diễn dạng hình học: Giả sử có ñồ thị G(V,E).
Biểu diễn ñỉnh: lấy các ñiểm trên mặt phẳng hay trên không gian tương ứng
với các phần tử của tập V và dùng ngay ký hiệu các phần tử này ñẻ ghi trên các
ñiểm tương ứng.
Biểu diễn cạnh: Nếu cạnh a với hai ñỉnh ñầu là x,y thì nó ñược biểu diễn
bằng ñoạn thẳng hay một ñoạn cong nối giữa hai ñiểm x, y và không ñi qua các
ñiểm tương ứng trong không gian.
Biểu diễn cung: nếu cung a có ñỉnh ñầu là x, ñỉnh cuối là y, thì nó ñược biểu
diễn bằng một ñoạn thẳng hoặc ñoạn cong ñược ñịnh hướng ñi từ x sang y và không
qua các ñiểm tương ứng trung gian khác.
Hình nhận ñược gọi là dạng biểu diễn hình học của ñồ thị G(V, E). ðôi khi
người ta cũng gọi dạng biểu diễn hình học là một ñồ thị.
b. ðề bài tập
Bài 1 Cho G ñồ thị gồm 4 phần G1, G2, G3 và G4 như sau:
a. Chỉ ra tập ñỉnh, cạnh(vô hướng,có hướng, khuyên,..) của mỗi ñồ thị ñã cho? Chỉ
loại ñồ thị ñó?
b. ðồ thị G, G1, G2, G3, G4 và G5 có liên thông ko? Nếu ñồ thị ko liên thông hãy
chỉ ra các thành phần liên thông?
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 6
c. ðồ thị G, G1, G2, G3, G4 và G5 có chu trình ko? Chỉ ra các chu trình của ñồ thị
(nếu có)?
c. Hướng dẫn giải
Bài 1
a.
Tên ñồ thị Tập ñỉnh V Tập cạnh E Loại ñồ thị
G1 1,2,3,4 (1,2);(1,4);(2,3);(2,4);(3,4) Vô hướng
G2 5,6,7 (5,6);(5,7);(6,7) Có hướng
G3 8,9 (8,9) Vô hướng
G4 0
G 1,2,3,4,5,6,7,8,9,0 (1,2);(1,4);(2,3);(2,4);(3,4);
(8,9)
(5,6);(5,7);(6,7)
Hỗn hợp
b.
Tên ñồ thị Tính liên thông Tên thành phần liên thông
G1 Có G1
G2 Có G2
G1
1
4 3
2 5
7 6
8
9
00
G2 G3
G4
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 7
G3 Có G3
G4 Có G4
G Không G1,G2,G3,G4
c.
Tên ñồ thị Có chu trình? Tên chu trình
G1 Có (1,2,4,1);(1,2,3,4,1);(2,3,4,2)
G2 Không
G3 Không
G4 Không
G Có (1,2,4,1);(1,2,3,4,1);(2,3,4,2)
d. Bài tập tự giải
Bài 1. Một quần ñảo có n( n ) hòn ñảo và hai hòn ñảo bất kì thuộc quần ñảo ñều
có số ñầu mối ñường ngầm tới một trong nhưng hòn ñảo nầy ñều nhỏ hơn n. Chứng
minh rằng từ một hòn ñảo tùy ý thuộc quần ñảo ta có thể ñi ñến một hòn ñảo bất kì
khác của quần ñảo bằng ñường ngầm.
Bài 2 Khi về nghỉ hè mỗi bạn học sinh của lớp 11A trường Lê Hồng Phong ñều
trao ñổi ñịa chỉ với ít nhất một nửa số bạn trong lớp. Chứng minh rằng trong thời
gian nghỉ hè mỗi bạn của lớp 11A ñều có thể báo tin trực tiếp hay gián tiếp cho các
bạn trong lớp.
Bài 3 Trong một cuộc họp có ñúng hai ñại biểu không que nhau và mỗi ñại biểu này
có một số lẻ người que ñến dự. Chứng minh rằng luôn luôn có thể xếp một số ñại
bieetr ngồi chen giữa hai ñại biể nói trên , ñể người ngồi giữa hai người mà anh(
chị) ta quen.
Hướng ñẫn:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 8
ðể giải ñược bài toán trên trước hết ta xây dựng các ñồ thị tương ứng, sau ñó vận
dụng kết quả của ñịnh lý 4.1, hệ quả 4.1 và ñịnh lý 4.2 mà suy ra kết luận.
Xuây dựng ñồ thị
• ðỉnh: Lấy các ñiểm trong mặt phẳng hay trong không gian tương ứng với các
hòn ñảo thuộc quần ñảo ( các bạn học sinh trong lớp 11A, các ñại biểu ñến
họp).
• Cạnh: Hai ñiểm x, y ñược nối bằng một cạnh khi và chỉ khi hai hòn ñảo x, y
có ñường ngầm trực tiếp với nhau( các bạn x, y trao ñổi ñịa chỉ cho nhau, các
ñại biểu x, y quen nhau)
- ðồ thị nhân ñược ký hiệu bằng G1 , (G2 , G3)
- ðồ thị G1 mô tả toàn bộ lưới ñường ngầm trong quần ñảo
- ðồ thị G2 mô tả toàn bộ quan hệ trao ñổi ñịa chỉ trong lớp 11A
- ðồ thị G3 mô tả toàn bộ quen biết trong các ñại biểu trong các ñại biểu ñến
dự họp.
Vận dụng kết quả các ñịnh lý ñể suy ra kết luận
- Do hai hòn ñảo bất kì ñều có tổng số ñầu mối ñường ngầm không nhỏ hơn n, nên
hai ñỉnh bất kì của ñồ thị G1 ñều có tổng bậc không nhỏ hơn n. Bởi vậy theo ñịnh lý
4.1. ñồ thị G1 liên thông, nên hai hòn ñảo bất kì có ñường hầm nối với nhau.
- Vì mỗi bạn học sinh trong lớp 11A trao ñổi ñịa chỉ với ít nhất một nửa số bạn tron
lớp, nên bậc của mỗi ñỉnh của G2 không nhỏ hơn một nửa số ñỉnh của ñồ thị. Khi ñó
, theo hệ quả 4.1. ñồ thị G2 liên thông. Bởi vậy hai ñỉnh x, y ñều có xích nối với
nhau. Khi ñó thông qua các bạn tương ứng với các ñỉnh thuộc xích , mà bạn tương
ứng với ñỉnh x báo tin ñược cho tương ứng với ñỉnh y và ngược lại.
- Hai ñại biểu không quen nhau, thì hai ñỉnh tương ứng không kề nhau. Mỗi ñại biểu
này lại có một số lẻ người quen ñến họp, nên trong ñồ thị liên thông G3 có ñúng hai
ñỉnh bậc lẻ và hai ñỉnh này lại không kề nhau. Khi dó, theo ñịnh lý 4.2, hai ñỉnh này
liên thông nên có ít nhất một xich nối giữa hai ñỉnh này. Giả sử là một trong
những mối xích nối giữa hai bậc lẻ này. Dựa vào ta sắp xếp các ñại biểu tương
ứng ngồi giữa hai người mà anh chị quen.
Bài 4 Cho G ñồ thị như sau:
Chỉ ra tập ñỉnh, cạnh(vô hướng,có hướng, khuyên,..) của mỗi ñồ thị ñã cho? Chỉ
loại ñồ thị ñó? ðồ thị có liên thông ko? Nếu ñồ thị ko liên thông hãy chỉ ra các
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 9
thành phần liên thông? ðồ thị có chu trình ko? Chỉ ra các chu trình của ñồ thị (nếu
có)?
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 10
Bài 2: Biểu diễn ñồ thị trên máy tính Mục tiêu
- Nêu ñược các cách biểu diễn ñồ thị và biểu diễn ñồ thị trên máy tính trên máy tính.
- ðưa ra ñược ma trận kề, danh sách các cạnh, cung tương ứng với 1 ñồ thị cho
trước.
- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.
- - Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
b. ðề bài tập
Bài 1 Cho G ñồ thị gồm 4 phần G1, G2, G3 và G4 như sau:
a. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng ma trận kề
b. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng danh sách cạnh(cung)
c. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng danh sách kề
Bài 2 Cài ñặt chương trình nhập danh sách kề của ñồ thị từ bàn phím và ñưa danh
sách ñó ra màn hình.
c. Hướng dẫn giải
Bài 1
G1
1
4 3
2 5
7 6
8
9
00
G2 G3
G4
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 11
Tên ñồ thị a. ma trận kề b. danh sách
cạnh(cung)
c.danh sách kề
G1 1 2 3 4
1 0 1 0 1
2 1 0 0 1
3 0 0 0 1
4 1 1 1 0
Danh sách cạnh
1 2
1 4
2 3
2 4
3 4
1 2 4
2 1 4
3 4
4 1 2 3
G2 5 6 7
5 0 0 1
6 1 0 1
7 0 0 0
Danh sách cung
5 6
5 7
6 7
5 6 7
6 7
G3 8 9
8 0 1
9 1 0
Danh sách cạnh
8 9
8 9
9 8
G4 0
0 0
G 1 2 3 4 5 6 7 8 9 0
1 0 1 0 1 0 0 0 0 0 0
2 1 0 0 1 0 0 0 0 0 0
3 0 0 0 1 0 0 0 0 0 0
4 1 1 1 0 0 0 0 0 0 0
5 0 0 0 0 0 0 1 0 0 0
Danh sách cung
1 2
1 4
2 1
2 3
2 4
1 2 4
2 1 4
3 4
4 1 2 3
5 6 7
6 7
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 12
6 0 0 0 0 1 0 1 0 0 0
7 0 0 0 0 0 0 0 0 0 0
8 0 0 0 0 0 0 0 0 1 0
9 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0
3 2
3 4
4 1
4 2
4 3
5 6
5 7
6 7
8 9
9 8
0
Bài 2 Chương trình nhập danh sách kề của ñồ thị từ bàn phím và ñưa danh sách ñó
ra màn hình
Phân tích bài toán :
Trong rất nhiều thuật toán làm việc với ñồ thị chúng ta thường xuyên phải thực hiện
các thao tác: Thêm hoặc bớt một số cạnh. Trong trường hợp này Cấu trúc dữ liệu
dùng ở trên là không thuận tiện. Khi ñó nên chuyển sang sử dụng danh sách kề liên
kết (Linked Adjancency List) như mô tả trong chương trình nhập danh sách kề của
ñồ thị từ bàn phím và ñưa danh sách ñó ra màn hình
Chương trình minh họa :
Program AdjList;
Const
maxV=100;
Type
link=^node;
node=record
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 13
v:integer;
next:link;
End;
Var
j,x,y,m,n,u,v:integer;
t:link;
Ke:array[1. .Vmax] of link;
Begin
Write(‘Cho so canh va dinh cua do thi:’); readln(m,n);
(*Khoi tao*)
for j:=1 to n do Ke[j]:=nil;
for j:=1 to m do
begin
write(‘Cho dinh dau va cuoi cua canh ‘,j,’:’);
readln(x,y);
new(t); t^.v:=x, t^.next:=Ke[y]; Ke[y]:=t;
new(t); t^.v:=y, t^.next:=Ke[x]; Ke[x]:=t;
end;
writeln(‘Danh sach ke cua cac dinh cua do thi:’);
for J:=1 to m do
begin
writeln(‘Danh sachcac dinh ke cua dinh ‘,j,’:’);
t:=Ke[j];
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 14
while t^.next<>nil do
begin
write(t^.v:4);
t:=t^.next;
end;
end;
readln;
End.
d. Bài tập tự giải
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 15
Bài 3: ðồ thị Euler Mục tiêu
- Kiểm tra ñược một ñồ thị bất kỳ có là ñồ thị euler hay không.
- Áp dụng ñược thuật toán tìm chu trình Euler, ñường Euler, với 1 ñồ thị cho trước.
- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau. Cài ñặt
ñược chương trình chuyển ñổi giữa các phương pháp.
- Cài ñặt ñược thuật toán Tìm chu trình Euler.
- Cài ñặt ñược thuật toán duyêt ñồ thị duyệt theo chiều sâu hoặc duyệt theo chiều
rộng.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
- Chu trình (t.ư. ñường ñi) ñơn chứa tất cả các cạnh (hoặc cung) của ñồ thị (vô
hướng hoặc có hướng) G ñược gọi là chu trình (t.ư. ñường ñi) Euler. Một ñồ thị
liên thông (liên thông yếu ñối với ñồ thị có hướng) có chứa một chu trình (t.ư.
ñường ñi) Euler ñược gọi là ñồ thị Euler (t.ư. nửa Euler).
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 16
ðịnh lý
ðồ thị (vô hướng) liên thông G là ñồ thị Euler khi và chỉ khi mọi ñỉnh của G ñều có
bậc chẵn.
Hệ quả
ðồ thị liên thông G là nửa Euler (mà không là Euler) khi và chỉ khi có ñúng hai
ñỉnh bậc lẻ trong G.
Thuật toán vạch ñược một chu trình Euler trong ñồ thị liên thông G có bậc của mọi
ñỉnh là chẵn theo thuật toán Fleury sau ñây.
Xuất phát từ một ñỉnh bất kỳ của G và tuân theo hai quy tắc sau:
1. Mỗi khi ñi qua một cạnh nào thì xoá nó ñi; sau ñó xoá ñỉnh cô lập (nếu có);
2. Không bao giờ ñi qua một cầu, trừ phi không còn cách ñi nào khác.
b. ðề bài tập
Bài 1: ðồ thị sau có là ñồ thị nửa Euler hay ñồ thị Euler ko? Giải thích?
c. Hướng dẫn giải
Bài 1: ðồ thị sau có là ñồ thị nửa Euler hay ñồ thị Euler ko? Giải thích?
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 17
ðồ thị G1 là ñồ thị nửa Euler
Thật vây, các ñỉnh a,b,e có bậc là 2,4,4 là bậc chẵn, các ñỉnh c và d có bậc là 3 là
bậc lẻ
ðồ thị G2 là ñồ thị nửa Euler
Thật vây, các ñỉnh c và d có bậc là 2 là bậc chẵn, các ñỉnh a và c có bậc là 1 là bậc
lẻ
a
b
e
c
d
G1
a
d
b
c
G2
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 18
ðồ thị G3 không là ñồ thị Euler
Thật vậy G3 có 3 ñỉnh a,d và g có bậc là 1 là bậc lẻ
G4
ðồ thị G4 là ñồ thị nửa Euler vì theo hệ quả..
Thật vây, các ñỉnh 3,4,5 có bậc là 2 là bậc chẵn, các ñỉnh 1 và 2 có bậc là 3 là bậc lẻ
Bài 2
g
a
d
b
c
e
f
G3
1
2
3 4
5
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 19
Xuất phát từ u, ta có thể ñi theo cạnh (u,v) hoặc (u,x), giả sử là (u,v) (xoá
(u,v)). Từ v có thể ñi qua một trong các cạnh (v,w), (v,x), (v,t), giả sử (v,w) (xoá
(v,w)). Tiếp tục, có thể ñi theo một trong các cạnh (w,s), (w,y), (w,z), giả sử (w,s)
(xoá (w,s)). ði theo cạnh (s,y) (xoá (s,y) và s). Vì (y,x) là cầu nên có thể ñi theo một
trong hai cạnh (y,w), (y,z), giả sử (y,w) (xoá (y,w)). ði theo (w,z) (xoá (w,z) và w)
và theo (z,y) (xoá (z,y) và z). Tiếp tục ñi theo cạnh (y,x) (xoá (y,x) và y). Vì (x,u) là
cầu nên ñi theo cạnh (x,v) hoặc (x,t), giả sử (x,v) (xoá (x,v)). Tiếp tục ñi theo cạnh
(v,t) (xoá (v,t) và v), theo cạnh (t,x) (xoá cạnh (t,x) và t), cuối cung ñi theo cạnh
(x,u) (xoá (x,u), x và u).
d. Bài tập tự giải
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 20
Bài 4: ðồ thị hamilton Mục tiêu
- Kiểm tra ñược một ñồ thị bất kỳ có là ñồ thị Hamilton hay không.
- Áp dụng ñược thuật toán tìm chu trình Hamilton, ñường Hamilton, với 1 ñồ thị
cho trước.
- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau. Cài ñặt
ñược chương trình chuyển ñổi giữa các phương pháp.
- Cài ñặt ñược thuật toán Tìm chu trình Halmiton.
- Cài ñặt ñược thuật toán duyêt ñồ thị duyệt theo chiều sâu hoặc duyệt theo chiều
rộng.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
- ðồ thị Hamilton(nửa Hamilton) là ñồ thị có chứa một chu trình(ñường ñi)
Hamilton
Hay
ðường ñi (x[1],x[2],…,x[n]) ñược gọi là ñường ñi Hamilton nếu x[i]≠x[j]
(1≤i<j≤n)
Chu trình (x[1],x[2],…,x[n],x[1]) ñược gọi là chu trình Hamilton nếu
x[i]≠x[j] (1≤i<j≤n)
Note! Cho tới nay, vẫn chưa tìm ra phương pháp với ñộ phức tạp ña thức ñể tìm chu
trình cũng như ñường ñi Hamilton trong trướng hợp ñồ thị tổng quát.
Có thể sử dụng thuật toán quay lui ñể liệt kê chu trình Hamilton
b. ðề bài tập
Bài 1: ðồ thị sau có là ñồ thị nửa Hamilton hay ñồ thị Hamilton ko? Giải thích?
c. Hướng dẫn giải
Bài 1: ðồ thị sau có là ñồ thị nửa Hamilton hay ñồ thị Hamilton ko? Giải thích?
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 21
ðồ thị G1 là ñồ thị Hamilton
ðồ thị G2 là ñồ thị nửa Hamilton
ðồ thị G3 không có chu trình hay ñường ñi Hamilton
a
b
e
c
d
G1
a
d
b
c
G2
g
a
d
b
c
e
f
G3
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 22
G4
ðồ thị G4 là ñồ thị Hamilton, vì có chu trình Hamilton (1,3,5,2,4,1)
d. Bài tập tự giải
1
2
3 4
5
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 23
Bài 5: Thảo luận cài ñặt ñồ thị, các thuật toán liệt kê chu trình Euler và Hamilton. Thảo luận về bài tập lớn Mục tiêu
- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.
- Chuyển ñổi giữa các kiểu biểu diễn ñồ thị trên máy tính.
- Nâng cao khả năng làm việc nhóm.
- Rèn luyện tư duy sáng tạo.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
Xem lại trong bài 3 và bài 4
b. ðề bài tập
Bài 1 Tìm chu trình Euler trong ñồ thị G.
Bài 2 Tìm chu trình Halmiton trong ñồ thị G.
c. Hướng dẫn giải
Bài 1 ðề bài : Cài ñặt chương trình tìm chu trình Euler trong ñồ thị G.
Cho ñồ thị G=(X,E) tồn tại chu trình Euler. Hãy tìm chu trình (chi trình Euler là
chu trình ñi qua tất cả các cạnh của ñồ thị, mỗi cạnh ñi qua ñúng một lần).
Phân tích bài toán :
ðầu vào: ðồ thị G
ðầu ra: Chu trình Euler (nếu có)
2. Thuật toán:
Xuất phát từ một ñỉnh u bất kỳ, khi ñi qua cạnh nào thì xoá cạnh ñó khỏi ñồ thị và
ghi lại từ trái sang phải. Khi thực hiện thuật toán cần lưu ý nếu gặp cạnh bắc cầu
giữa 2 thành phần liên thông thì ta phải xoá hết thành phần liên thông rồi mới xoá
ñến cạnh bắc cầu.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 24
Khi xoá cạnh bắc cầu thì phải loại hết các ñỉnh trơ trọi (nghĩa là không kề với bất cứ
ñỉnh nào thuộc ñồ thị).
Cấu trúc dữ liệu:
Biểu diễn ñồ thị bằng ma trận kề a(i,j), do ñó lưu ý khi xoá ñi một cạnh ta chỉ việc
gán a(i,j)=a(j,i)=0, ñồng thời phải lưu cạnh vừa xoá vào một mảng khác: Mảng Ctr.
Mảng lt: array [1…Nmax] of integer dùng trong thủ tục tìm thành phần liên thông
(giống như một thuật toán tìm thành phần liên thông trình bày ở trên).
Mảng dd: array [1…Nmax] of Boolean, giá trị dd[i] cho biết ñỉnh i bị loại khỏi ñồ
thị hay chưa. Nếu bị lại thì dd[i]=True; ngược lại dd[i]=False;
Thủ tục
Procedure Euler_Cycle;
Begin
STACK:=∅ ; CE:=∅ ;
Chon u la mot dinh nao do cua do thi;
STACK← u;
While STACK<>∅ do
Begin
X:=top(STACK); (* x la phan tu dau STACK)
If Ke(x)<>∅ then
Begin
Y:=dinh dau tien trong danh sach Ke(x);
STACK← y;
(* loai bo canh (x,y) khoi do thi *)
Ke(x):=Ke(x)\ { y} ;
Ke(y):=Ke(y)\{ x} ;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 25
End
Else
Begin
x⇐ STACK; CE⇐ x;
End;
End;
End;
Chương trình minh họa :
Program Chu_trinh_Euler;
Const Nmax=100;
Emax=100;
Var a:array[1…Nmax,1..Nmax]of integer;
Ctr: array[1…Emax,1,2]of integer;
dd: array[1…Nmax]of Boolean;
lt: array[1…Nmax]of integer;
SolC,N:integer;
(*Biến Solc là số cạnh của chu trình, sẽ tăng lên một ñơn vị mỗi khi ta ñi qua
một cạnh*).
Program Timtplt(k:integer);
(* Thủ tục này tìm thành phần liên thông giống như thuật toán tình thành phần
liên thông trình bày ở trên chỉ khác một ñiểm là ta chỉ tìm tplt ñối với các ñỉnh chưa
bị loại khỏi ñồ thị *).
Var i:integer;
Begin lt[k]:=sotp;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 26
For i=1 to N do
If dd[i] and (lt[i]=0) and(a[i,k]=1)then
Begin
lt[i]:=sotp;
Timtplt(i);
End;
End;
Function KTLT (u,v:integer):Boolean;
(* Hàm này kiểm tra xem khi ta xoá cạnh (u,v) ñi thì ñồ thị còn liên thông nữa hay
không? Nếu còn thì số tplt luôn bằng 1. ðây coi như kiểm tra cạnh (u,v) có phải là
cạnh bắc cầu hay không*).
Var i:integer;
Begin(* ðầu tiên ta phải xoá cạnh (u,v) khỏi ñồ thị rồi mới tiến hành kiểm
tra *).
a[u,v]:=0;a[u,v]:=0;
Fillchar(lt,sizeof(lt),0);
(* ðoạn mã sau tìm số tplt của ñồ thị ở ñiểm ñang xét *).
Sotp:=0;
For i=1 to N do
If dd[i] and (lt[i]=0)then
Begin
inc(sotp);
Timtplt(i);
End;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 27
If sotp=1 then KTLT=True
Else
Bengin (*nếu không có cạnh bắc cầu thì khi khôi phục
lại cạnh (u,v)*).
a[u,v]:=1
a[v,u]:=1
KTLT:=False
End;
End;
Procedure Timchutrinh;
Var i,u,dem:integer;
Begin solc:=0;
u:=1;
(* Chu trình của ta xuất phát từ ñỉnh 1, tuy nhiên ñiều này không bắt buộc *)
For i=1 to N do
dd[i] true;
(* Khởi tạo tất cả các giá trị dd[i]=True nghĩa là chưa có ñỉnh nào bị
loại *)
REPEAT
Dem:=0;
(* Biến ñếm là số cạnh kề với ñỉnh u *)
Begin
For i=1 to N do
If a[u,i]=1 then
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 28
Begin (*xoá cạnh (u,i) khỏi ñồ thị *)
a[u,i]:=0
a[i,u]:=0
(*Loại ñỉnh u khỏi ñồ thị*)
dd[u]:=False;
(*ðua cạnh (u,i) vào chu trình*).
inc(solC);
Ctr[solC,1]:=u;
Ctr[solC,2]:=i;
Break;
End;
End
Else
(*Ngược lại nếu còn nhiều cạnh nối với u ta tìm một cạnh không phải là cạnh
bắc cầu và xoá cạnh ñó ñồng thời ñưa nó vào chu trình*)
If dem>1 then
Begin
For i=1 to N do
If (a[u,i]=1 and dd[i] and KTLT(u,i)then
(*Nếu cạnh (u,i) thoả mãn không phải là cạnh bắc cầu thì ta chọn:
Nghĩa là nó phải kề với u, chưa bị loại khỏi ñồ thị và sau khi xoá cạnh kề ñó
thì ñồ thị vẫn liên thông. Riêng ñiều kiện thứ 3 ta dùng hàm KTLT(u,i) ñể
kiểm tra xem khi xáo cạnh (u,i) ñi thì ñồ thị còn liên thông nữa hay không*).
Begin
(*ðoạn mã sau xoá cạnh (u,i) và ñưa cạnh này
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 29
vào chu trình*).
a[u,i]:=0
a[i,u]:=0
inc(solC);
Ctr[solC,1]:=u;
Ctr[solC,2]:=i;
Break;
(*Sau khi tìm ñược ñỉnh i thì ta phải thoát khỏi vòng lặp For nếu không có
lệnh Break thì chương trình sẽ chạy sai*).
End;
End;
(*Chuẩn bị cho phép tiếp chu trình của chúng ta lại xuất phát từ ñỉnh*)
u:=1;
UNTIL dem=0;
End;
Procedure Ghifile;
Var f:text;
I:integer;
Begin
Assign(f,’kq.out’);Rewrite(f);
For i:=1 to solC do
writeln(f,Ctr[i,1],’ ‘,Ctr[i,2]);
Close(f);
BEGIN
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 30
Docfile;
Timchutrinh;
Ghifile;
END.
Bài 2 ðề bài : Liệt kê tất cả các chu trình Hamilton của ñồ thị
Phân tích bài toán :
Thuật toán sau ñây ñược xây dựng dựa trên cơ sở thuật toán quay lui cho phép liệt
kê tất cả các chu trình Hamilton của ñồ thị.
Hình dưới ñây mô tả cây tìm kiếm theo thuật toán vừa mô tả.
ðồ thị và cây liệt kê chu trình Hamilton của nó theo thuật toán quay lui.
Trong trường hợp ñồ thị có không quá nhiều cạnh thuật toán trên có thể sử dụng ñể
kiểm tra ñồ thị có phải là Hamilton hay không.
Chương trình minh họa :
Procedure Hamilton(k);
(* liet ke cac chu trinh Hamilton thu duoc bang viec phat trien day dinh (X[1],. . .
, X[k-1]) cua do thi G=(V,E) cho boi danh sach ke: Ke(v), v∈ V *)
begin
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 31
for y ∈ Ke(X[k-1]) do
if (k =N+1) and (y=v0) then Ghinhan(X[1],. . . , X[n], v0)
else
if Chuaxet[y] then
begin
X[k]:=y;
Chuaxet[y]:=false;
Hamilton(k+1);
Chuaxet[y]:=true;
end;
end;
(* Main program*)
begin
for v ∈ V do Chuaxet[v]:=true;
X[1]:=0; (* v0 la mot dinh nao do cua do thi *)
Chuaxet[v0]:=false;
Hamilton(2);
end.
d. Bài tập tự giải
Bài tập 1: Hội nghị bàn tròn
Tổng thư ký ðại hội ñồng Liên hợp quốc triệu tập một cuộc họp có N nhà
ngoại giao của N tổ chức tham gia. Các ñại diện ngoại giao ñược bố trí ngồi quanh
một bàn tròn. Giữa một số tổ chức có quan hệ căng thẳng, vì vậy không thể xếp họ
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 32
ngồi cạnh nhau ñược. Thông tin về quan hệ giữa các tổ chức ñược cho dưới dạng
cặp số nguyên i, j nếu giữa 2 tổ chức này có quan hệ căng thẳng.
Hãy lập trình giúp Tổng thư ký Liên hợp quốc bố trí chỗ ngồi quanh bàn họp. Các
tổ chức ñược ñánh số từ 1 tới N, 0 < N <= 500.
Dữ liệu vào: từ file CONF.INP, dòng ñầu tiên chứa số nguyên N, các dòng
sau, mỗi dòng một cặp số i, j cho biết các ñại diện i và j không ngồi cạnh nhau
ñược. Kết thúc là một dòng chứa 2 số 0.
Kết quả: ñưa ra file CONF.OUT. Nếu không có cách bố trí thỏa mãn yêu
cầu thì ñưa ra thông báo KHONG CO, trong trường hợp ngược lại – ñưa ra dãy N
số nguyên xác ñịnh vị trí ai ngồi cạnh ai quanh bàn tròn.
Ví dụ:
CONF.INP CONF.OUT
11 1 9 7 4 11 5 8 2 10 3 6
1 4
1 7
5 7
10 7
10 8
10 9
3 4
0 0
Bài tập 2: Kiểm tra ñường
Một trạm quảng ñường giao thông phải chịu trách nhiêm về tình trạng của
một mạng lưới giao thông nối giữa các ñiểm dân cư. Hàng tháng, họ phải cử một
ñội ñi kiểm tra một vòng qua khắp mạng lưới ñể xem xét tình trạng hiện thời của
các ñường giao thông nhằm báo sửa chữa kịp thời nếu có nhu cầu. Hãy viết chương
trình nhập vào mạng lưới giao thông và giúp trạm quyết ñịnh lộ trình của ñội kiểm
tra sao cho có thể thăm tất cả các con ñường mà tổng chiều dài ñoạn ñường ñi qua
là nhỏ nhất.
Bài tập 3: Mã ñi tuần
Hãy cài ñặt chương trình xác ñịnh lộ trình của con mã trên bàn cờ 8x8 ô bắt
ñầu từ ô (i, j) ñi qua tất cả các ô của bàn cờ vàmỗi ô chỉ 1 lần duy nhất.
Mở rộng với trường hợp bàn cờ kích thước NxN.
Bài tập 4: Hội nghị bàn tròn
Có 12 người ngồi chung 1 bàn tiệc tròn. Mỗi người có ít nhất 6 người quen.
Hãy chỉ ra cách sắp xếp sao cho mỗi người ñều ngồi cạnh người mình quen . Tổng
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 33
quát, hãy sắp N người ngồi chung quanh bàn tròn sao cho mỗi người ñều ngồi cạnh
người mình quen. Biết mỗi người có ít nhất (N + 1)/2 người quen.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 34
Bài 6 Thuật toán tìm kiếm trên ñồ thị và ứng dụng Mục tiêu
- Trình bày ñược ý tưởng, cách cài ñặt và cài ñặt ñược thuật toán BFS, DFS.
- Nêu ưu nhược của từng thuật toán ñối với từng loại ñồ thị.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
- Rèn luyện tư duy sáng tạo.
a. Nhắc lại lý thuyết
b. ðề bài tập
Bài 1 Dùng cây ñể mô tả kết quả duyệt chiều sâu và duyệt theo chiều rộng trên ñồ
thị sau:
Bài 2 Cho ñồ thị G=(X,E) với tập các ñỉnh X và tập các cung E. Xét xem ñồ thị có
bao nhiêu thành phần liên thông, mỗi thành phần liên thông bao gồm những ñỉnh
nào?
Bài 3 Thuật toán tìm ñường ñi theo chiều sâu (thuật toán duyệt theo chiều sâu)
Bài 4 Thuật toán tìm ñường ñi theo chiều rộng (thuật toán duyệt theo chiều rộng)
c. Hướng dẫn giải
Bài 1 Dùng cây ñể mô tả kết quả duyệt chiều sâu và duyệt theo chiều rộng trên ñồ
thị sau:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 35
Duyệt rộng
Duyệt sâu:
Bài 2 Thuật toán tìm số thành phần liên thông
Cho ñồ thị G=(X,E) với tập các ñỉnh X và tập các cung E. Xét xem ñồ thị có
bao nhiêu thành phần liên thông, mỗi thành phần liên thông bao gồm những ñỉnh
nào?
Phân tích bài toán :
3 5
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 36
8 2 6 3
1
2
2 7 9 2
1 1 3 1
4 1
ðồ thị với các thành phần LT
ðầu vào:
a. Biểu diễn ñồ thị bằng ma trận kề
Dothi.txt Kq.txt
9
0 1 1 1 0 0 0 0 0
1 0 1 0 0 0 0 0 0
1 1 0 1 0 0 0 0 0
1 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 0 1
So tph cua do thi la:3
TPLT 1 bao gom cac dinh: 1 2 3 4
TPLT 2 bao gom cac dinh: 5 8
TPLT 3 bao gom cac dinh: 6 7 9
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 37
0 0 0 0 0 1 0 0 1
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 0 0
Cấu trúc dữ liệu
ðầu tiên ñánh số các ñỉnh là 0
(Dùng một mảng biểu diễn các thành phần là mảng chúng ta cần tìm, ban ñầu
ta gán tất cả các giá trị của mảng bằng 0)
Lấy ra ñỉnh L gán lt[i]:=1
+ Duyệt các ñỉnh kề của 1 gặp ñỉnh tiếp theo là ñỉnh 2 chưa ñược ñánh số ta
ñánh số 1 gán lt[2]:=1 sang bước tiếp theo.
+ Duyệt các ñỉnh kề của 2, gặp ñỉnh 1 ñược ñánh số rồi nên bỏ qua, gặp ñỉnh
chưa ñánh số nên ñánh số 1, gán lt[4]:=1 sang bước tiếp theo.
+ Duyệt các ñỉnh kề của 4, gặp ñỉnh 1 ñánh số rồi nên bỏ qua. Gặp ñỉnh 2 ñánh
số rồi nên bỏ qua. Gặp ñỉnh 3 chưa ñánh số nên ñánh số 1, lt[3]:=1 sang bước tiếp
theo.
+ Duyệt các ñỉnh kề của 3 gặp toàn các ñỉnh ñánh số rồi nên không ñánh số
nữa dừng việc ñánh số.
Như vậy ta ñã tìm ñược 1 thành phần liên thông.
Lấy ra một ñỉnh chưa ñánh số ví dụ ta lấy ñỉnh 6
Ta lại làm như trên ta lại tìm ñược thành phần liên thông khác.
Như vậy ta rút ra ñược Cấu trúc dữ liệu của bài toán này.
ðối với ñồ thị và các cạnh thì ta có thể dùng ma trận kề hoặc danh sách kề, và
nên ñọc từ file ñể ñơn giản hoá.
Dùng một mảng lt[1…n] biểu diễn TPLT lt[i]:=K nếu ñỉnh i thuộc thành phần
liên thông.
Chương trình minh họa :
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 38
a. Biều diễn ñồ thị bằng ma trận kề.
a(i,j)=1 nếu 2 ñỉnh i và j kề nhau và =0 nếu 2 ñỉnh i và j không kề nhau.
Program tim_thanh_phan_lien_thong;
Const Nmax=100;
Type mang=array[1…Nmax] of integer;
Var lt:mang;
a: array[1…Nmax, 1…Nmax] of byte;
N:integer;
Sotp: integer;
(*Thủ tục này ñọc từ file dothi.txt số N là số ñỉnh của ñồ thị ma trận kề biểu diễn ñồ
thị *)
Procedure Docfile;
Var i,j: integer;
f: text;
Begin
Assign(f,’dothi.txt’);reset(f);
Readln(f,N);
For i:=1 to N do
Read(f,a[i,j]);
Close(f);
End;
(*Thủ tục ñệ quy này dùng ñể tìm các ñỉnh thuộc một thành phần liên thông *)
Procedure Docfile;
Var i,j: integer;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 39
Begin lt[k]:=sotp;
(*Duyệt qua các ñỉnh của ñồ thị *)
For i:=1 to N do
(*Nếu ñỉnh i kề với k và chưa ñánh dấu thì ta gọi thủ tục ñệ quy. Tìm
LT nghĩa là lại ñánh dấu và duyệt các ñỉnh kề của i *)
lf (lt[i]=0)and(a[i,k]=1)then
TimLT(i);
End;
(*Thủ tục này ñược coi như bước 2 trong vớ dụ *)
Procedure TimTPLT;
Var i: integer;
Begin sotp:=0;
(*Duyệt các ñỉnh chưa ñược ñánh dấu *)
For i:=1 to N do
(*Nếu có một ñỉnh chưa thuộc thành phần liên thông nào lt[i]=0 nghĩa
là tìm ra một thành phần mới nên ta tăng số lượng thành phần và bắt ñầu ta ñi
tìm thành phần liên thông mới ñó bằng thủ tục ñệ quy TimLT(i)*)
lf lt[i]=0 then
Begin
Inc(sotp);
TimLT(i);
End;
End;
(*Thủ tục in ra các thành phần liên thông của ñồ thị *)
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 40
Procedure Ghifile;
Var i,j: integer;
Begin
Writeln(‘so thanh phan lien thong cua do thi lµ: ;sotp);
For i:=1 to sotp do
Begin
Writeln(‘TPLT’, i ,’bao gom cac dinh:’);
For j:=1 to N do
(*nếu j thuộc thành phần liên thông thứ i thì in ra *)
lf lt[j]=i then
Write(J,’ ‘);
Writeln;
End;
Readln;
End;
BEGIN
Docfile;
Tim TPLT;
Ghifile;
END.
b. Biểu diễn ñồ thị bằng danh sách cạnh
Ma trận của chúng ta (ở ví dụ trên) ñược viết dưới dạng:
2 3 4 9
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 41
1 3 0 1 2 3 4
2 4 0 2 1 3
1 3 0 3 2 4
8 0 0 4 1 3
7 9 0 5 8
6 9 0 6 7 9
5 0 0 7 6 9
6 7 0 85
9 6 7
a[i,9] là số lượng các ñỉnh kề với ñỉnh i;
a[i,j] chính là các ñỉnh kề với các ñỉnh i (j=1,2,3,…)
Khi ñó thủ tục Docfile ñược viết lại như sau:
Procedure Docfile;
Var i,j,t: integer;
f: text;
Begin Assign(f,’dothi.txt’);reset(f);
Readln(f,N);
For i:=1 to sotp do
Bengin
Read(f,t);
While not eoln(f) do
Begin
Read(f,t);
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 42
Inc(j);
a[i,j]:=t;
End;
a[i,0]:=j;
End;
Close(f);
End;
Thủ tục Ghifile và thuc tục TimTPLT không có gì thay ñổi
Thủ tục TimTPLT thay ñổi như sau:
Procedure TimLT (k:integer);
Var i: integer;
Begin
Lt[k]:=sotp;
For i:=1 to a[k,0] do
If lt[a[k,i]]=0 then
TimLT(a[k,i]);
End;
Bài 3 ðề bài : Thuật toán tìm ñường ñi theo chiều sâu (thuật toán duyệt theo chiều
sâu).Tìm ñường ñi giữa hai ñỉnh xp và kt trên ñồ thị G vô hướng và không có trọng
số.
Phân tích bài toán :
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 43
Thuật toán của bài toán này cũng giống như thuật toán tìm thành phần liên
thông của ñồ thị. Trong phần Cấu trúc dữ liệu có dùng mảng trước ñể lưu ñường ñi
từ ñỉnh xp ñến ñỉnh kt.
Chương trình minh họa :
Program Duyetchieusau;
Const Nmax=100;
Type Mang=array[1…Nmax] of integer;
Matran= array[1…Nmax,1…Nmax] of integer;
Var a:Matran;
so,duong:mang;
N:integer;
(*thủ tục ñọc tệp và ghi tệp giống như bài trước chỉ ñọc thêm hai ñỉnh xp và kt
*)
Procedure Duyet (k:integer);
Var i:integer;
Begin
For i:=1 to N do
(*Duyệt các ñỉnh kề với k *)
lf (a[i,k]=1)and(truoc[i]=0)then
Begin (*ta gán ñỉnh ñã ñi trước ñỉnh i là ñỉnh k *)
Truoc[i]:=k;
Duyet(i);
End;
End;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 44
Procedure Duyetsau;
Var i:integer;
Begin
For i:=1 to N do truoc[i]:=0
Truoc[xp]:=-1;
Duyet(xp);
End;
Procedure Timduong;
(*thủ tục này giống thủ tục tìm ngược trong duyệt chiều rộng, nhưng chỉ tìm
một ñường ñi ngắn nhất trong rất nhiều ñường ñi ngắn nhất từ xp ñến kt *).
Var i,u: integer;
Begin
sold:=0;
u:=kt;
REPEAT
Inc(sold);
Duong[sold]:=u;
U:=truoc[u];
UNTIL u=-1;
End;
BEGIN
Doctiep;
Duyetsau;
Timduong;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 45
Ghitep;
END.
Bài 4 ðề bài : Thuật toán tìm ñường ñi theo chiều rộng (thuật toán duyệt theo chiều
rộng). Cho ñồ thị vô hướng G=(X,E). Hãy tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và
kt cho trước (ñường ñi ngắn nhất là xích có 2 ñầu là xp và kt và ñi qua ít cung hoặc
ít ñỉnh nhất).
Phân tích bài toán
Sử dụng hàng ñợi ñể giải quyết bài toán này. Cách ñưa một ñỉnh của ñồ thị và
lấy 1 ñỉnh ra sử dụng phải tuân theo một quy tắc nhất ñịnh.
Sử dụng một mảng ñánh dấu ñường ñi truoc: array[1..Nmax] of integer
Khi ñi từ ñỉnh xp mà muốn có ñường ñi ngắn nhất ñến u thì ta phải qua ñỉnh
truoc [u], muốn có ñường ñi ngắn nhất ñến truoc [u] thì ta phải ñi qua truoc [truoc
[u] ],…
Yêu cầu: Sau thủ tục duyệt theo chiều rộng thì ta phải tìm ñược mảng truoc.
Khởi tạo giá trị ban ñầu của mảng truoc bằng 0.
B1: Khởi tạo hàng ñợi.
ðưa xp vào hàng ñợi. Gán truoc [xp]: = -1
B2: REPEAT
Lấy 1 ñỉnh ra khỏi hàng ñợi. Giả sử ñỉnh u.
Duyệt những ñỉnh kề với u, giả sử duyệt ñến ñỉnh v.
- Nếu trước [v] = 0 thì ta ñưa v vào hàng ñợi ñồng thời gán truoc [v]: = u.
Nghĩa là muốn ñi qua v thì phải ñi qua ñỉnh trước ñó là u;
B3: Kiểm tra v có phải là kt hay không, nếu có thì thoát khỏi thủ tục;
Nếu truoc [v] <> 0 thì bỏ qua.
UNITL (hàng ñợi rỗng) or (truoc [kt]<>0
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 46
Hàng ñợi rỗng nghĩa là không còn ñỉnh nào ở trong hàng ñợi.
Trên ñây là sườn của thủ tục duyệt chiều rộng, nếu sau những bước này mà
truoc [kt] = 0 nghĩa là không tồn tại ñường ñi từ xp ñến kt.
B4: (Tim ñường ñi thông qua mảng truoc)
Dùng một mảng duong: array [1..Nmax] of integer ñể biểu diễn các ñỉnh nằm
trên ñường ñi. Mảng này thể hiện ñường ñi ngược từ kt về xp. Do ñó khi in kết quả
ra màn hình ta phải in ngược từ cuối mảng.
Khởi ñầu u: = kt;
sold: = 0 (số lượng ñỉnh trên ñường ñi khởi ñầu bằng 0)
REPEAT
Tăng sold lên 1 ñơn vị
gán duong [sold]: = u;
ñi ngược lại bước trước u: = truoc [u];
UNILT u = -1
B5: In kết quả.
Thuật toán hơi khó hiểu. Bạn sẽ thấy rõ trong phần cài ñặt chương trình.
Cấu trúc dữ liệu
Mảng 2 chiều a (ij) biểu diễn ma trận liên thuộc các ñỉnh và các cung của ñồ
thị.
Mảng truoc và mảng duong mô tả như trên.
Mảng q (quene) mô tả cấu trúc của hàng ñợi.
Thủ tục
Program Duyet _chieu_rong;
Const Nmax = 100;
Type mang = array [1..Nmax] of integer;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 47
Var q,truoc,duong:mang;
A:array [1..Nmax, 1..Nmax] of byte;
Sold; N,xp,kt,qf,ql: integer;
(* qf- queue first là con chạy ñầu hàng ñợi
ql-queue last là con chạy cuối hàng ñợi*)
Chương trình minh họa :
Procedure Docfile;
Var ij: integer;
f: text;
Begin
Assign (f, ‘dothi.txt’); reset (f);
Readln (f,N);
For i:= 1 to N do
Forj:= 1 to N do
Read (f,a[ i j]);
Close(f);
Readln (f,xp,kt);
End;
(*Thủ tục khởi ñộng hàng ñợi *);
Procedure InitQ;
Begin
ql: = 1
qf: = 0
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 48
End;
(*Thủ tục ñưa một ñỉnh vào cuối hàng ñợi *)
Prcedure Put (k:integer);
Begin
q[ql]: = k;
inc (ql);
End;
(*Hàm lấy một ñỉnh ra khỏi hàng ñợi – lấy ở ñầu hàng ñợi*)
Function Get:integer;
Begin
Get:= q[qf];
inc (qf);
End;
(*Hàm kiểm tra hàng ñợi rỗng hay không*)
Function Qempty: Boolean;
Begin
Qempty: = (qf>ql);
End;
(*Thủ tục duyệt chiều rộng *)
Procedure DuyetCR;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 49
Var v,u:integer;
Begin InitQ;
Put (xp;
Truoc [xp]: = -1;
REPEAT
U: = Get;
(Duyệt các ñỉnh kề của u*)
For v: = 1 to N do
If (a[u,v] = 1 and (truoc [v]= 0) then
Beign
(*Nếu v kề với u và chưa ñi qua thì ñánh dấu và ñưa v vào hàng ñợi*)
Truoc [v]: = u;
Put (v);
End;
UNILT Qempty or (truoc [kt] <>0);
End;
(*Thủ tục tìm mảng ñường ñi từ xp ñến kt ở dạng ngược *)
Procedure Timduong;
Var u:integer;
Begin sold: = 0;
u:= kt;
REPEAT
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 50
inc (sold);
Duong[sold]:=u;
u:=truoc[u]:
UNILT u = xp;
End;
(*Thủ tục in kết quả ra màn hình *)
Procedure Inkq;
Var i:integer;
Begin
If truoc[kt]= 0 then
Writeln (‘khong co duong di tư ‘,xp, ‘den’, kt)
else
Begin Writeln (‘Duong di tư ‘, xp, ‘den’, kt);
(*Khi in phải in ngược mảng ñường từ sold trở về 1*)
For i: = sold downto 1 do
Write (duong[i], ‘ ‘);
End;
Realn;
End;
BEGIN
Docfile;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 51
Duyet CR;
(*Chắc chắn rằng nếu có ñường ñi ñến ñỉnh kt thì ta mới tìm mảng ñường *)
If truoc[kt]<>0 then
Timduong;
Inkq;
END.
d. Bài tập tự giải
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 52
Bài 7: Cây và cây khung Mục tiêu
Mục tiêu của bài này người học có khả năng:- Xác ñịnh ñược một ñường ñi, một
chu trình trong ñồ thị bất kỳ.
- Biểu diễn ñồ thị trên máy tính bằng các phương pháp khác nhau.
- Áp dụng ñược thuật toán Kruskal và Prim ñể tìm cây khung nhỏ nhất ứng với một
ñồ thị xác ñịnh. Cài ñặt ñược thuật toán.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
Các ñịnh nghĩa: ñồ thị, cạnh, cung, ñỉnh kề, cây, cây khung.
Các phương pháp biển diễn ñồ thị trên máy tính
ðịnh lý 3.4.2: Cho T là một ñồ thị có n ≥ 2 ñỉnh. Các ñiều sau là tương ñương:
1) T là một cây.
2) T liên thông và có n−1 cạnh.
3) T không chứa chu trình và có n−1 cạnh.
4) T liên thông và mỗi cạnh là cầu.
5) Giữa hai ñỉnh phân biệt bất kỳ của T luôn có duy nhất một ñường ñi sơ cấp.
6) T không chứa chu trình nhưng khi thêm một cạnh mới thì có ñược một chu
trình duy nhất.
Bài toán cây khung nhỏ nhất
Thuật toán Kruskal với ý tưởng “chọn dần”
B1: Chọn cạnh trọng số nhỏ nhất
B2: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại
B3: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại, mà ko tạo thành chu
trình.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 53
Lặp lại bước 3 cho tới khi chọn ñược n-1 cạnh.
Thuật toán Prim với ý tưởng “lan tỏa”. Giả sử lan tỏa từ ñỉnh A
B1: Chọn cạnh trọng số nhỏ nhất thuộc A (tức có 1 ñầu là ñỉnh A)
Giả sử là cạnh (A,B)
B2: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại thuộc A hoặc B (tức có
1 ñầu là ñỉnh A hoặc B). Giả sử là cạnh (C,B) hoặc (C,A)
B3: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại thuộc A hoặc B hoặc
C, mà ko tạo thành chu trình.
Lặp lại bước 3 cho tới khi chọn ñược n-1 cạnh.
b. ðề bài tập
Bài tập 1: Cho ñồ thị vô hướng có trọng số sau:
Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung), danh sách lien kết.
Áp dụng thuật toán Prim( xuất phát tại ñỉnh 1) hoặc Kruskal tìm cây khung nhỏ nhất
cho ñồ thị trên.
Bài 2 Áp dụng thuật toán Kruskal ñể tìm cây khung nhỏ nhất của ñồ thị cho trong
hình dưới ñây:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 54
c. Hướng dẫn giải
Bài tập 1:
- Thuật toán Prim với ý tưởng “lan tỏa”, xuất phát từ ñỉnh 1 “lan tỏa” ta có các cạnh
tạo thành cây khung nhỏ nhất lần lượt là: (1,5); (5,4);(4,2) và (4,3)
Gọi V(E) là tập các ñỉnh(cạnh) của ñồ thị,
Vt(Et) là tập các ñỉnh(cạnh) của cây khung nhỏ nhất cần tìm.
Thuật toán Prim với các bước thứ tự ñược miêu tả trong bảng sau:
Bước E Et Vt
Khởi tạo {} {1}
1 {(1,5)} {1,5}
2 { (1,5); (5,4); } {1,5,4}
3 { (1,5); (5,4);(4,2) } {1,5,4,2}
4 { (1,5); (5,4);(4,2) và
(4,3) }
{1,5,4,2,3}=V => dừng
Chú ý:
Thuật toán Kruskal với ý tưởng “chọn dần” các ñỉnh có trọng số nhỏ nhất trong các
cạnh còn lại, nếu ko tạo thành chu trình. Quá trình lặp lại cho tới khi chọn ñược n-1
cạnh.
Các cạnh ñược chọn ñể tạo thành cây khung nhỏ nhất lần lượt là: (2,4);(4,5);(4,3) và
(1,5)
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 55
- Thuật toán Prim với ý tưởng “lan tỏa”, xuất phát từ ñỉnh 4
“lan tỏa” ta có các cạnh tạo thành cây khung nhỏ nhất lần lượt là: (4,2);(4,5);(4,3)
và (1,5)
Với các bước thứ tự (tự làm)
Bài 2:
Bước khởi tạo. ðặt T:=Æ . Sắp xếp các cạnh của ñồ thị theo thứ tự không giảm của
ñộ dài ta có dãy:
(3,5) , (4,6) , (4,5) , (5,6) , (3,4) , (1,3) , (2,3) , (2,4) , (1,2)
dãy ñộ dài tương ứng của chúng
4, 8, 9, 14, 16, 17, 18, 20, 23.
Ở ba lần gặp ñầu tiên ta lần lượt bổ sung vào tập T các cạnh (3,5) , (4,6) , (4,5). Rõ
ràng nếu thêm cạnh (5,6) vào T thì sẽ tạo thành 2 cạnh (4,5), (4,6) ñã có trong T chu
trình. Tình huống tương tự cũng xảy ra ñối với cạnh (3,4) là cạnh tiếp theo của dãy.
Tiếp theo ta bổ sung cạnh (1,3), (2,3) vào T và thu ñược tập T gồm 5 cạnh:
T = { (3,5) , (4,6) , (4,5) , (1,3) , (2,3) }
Chính là tập cạnh của cây khung nhỏ nhất cần tìm.
d. Bài tập tự giải
Bài tập 1: Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung), danh sách lien
kết.
Áp dụng thuật toán Prim và Kruskal tìm cây khung nhỏ nhất cho ñồ thị sau:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 56
Bài tập 2 : Mạng an toàn
Cho một mạng N (N <= 20) máy tính ñược ñánh số từ 1 ñến N. Sơ ñồ mạng
ñược cho bởi hệ gồm M kênh (ñoạn) nối trực tiếp giữa một số cặp máy trong mạng,
m kênh tương ứng với m cặp. Cho biết chi phí truyền 1 ñơn vị thông tin theo mỗi
kênh của mạng.
Người ta cần chuyển một bức thông ñiệp từ máy s ñến máy t. ðể ñảm bảo an
toàn, người ta chuyển bức thông ñiện này theo hai ñường truyền tin khác nhau (tức
không có kênh nào) của mạng ñược sử dụng trong cả hai ñường truyền tin; cho phép
hai ñường truyền tin cùng ñi qua một số máy tính). Chi phí của một ñường truyền
ñược hiểu là tổng chi phí trên các kênh của nó. ðơn giá ñường truyền từ máy s sang
máy t ñược tính như sau:
Với hai máy s và t, cùng bức thông ñiệp có ñộ dài là 1 ñơn vị thông tin, ñơn
giá truyền cho cặp (s, t) ñược tính bằng tổng chi phí chuyển thông ñiệp an toàn
(bằng tổng chi phí của hai ñường truyền tin) là nhỏ nhất.
Mạng truyền tin nói trên thỏa mãn tính chất an toàn theo nghĩa là từ một máy
bất kỳ luôn truyền ñược (một cách an toàn) thông ñiệp tới một máy bất kỳ khác. Khi
một mạng an toàn, người ta tính ñược ñơn giá của mạng là tổng ñơn giá mọi ñường
truyền từ một máy bất kỳ tới một máy bất kỳ khác.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 57
Ma trận ñơn giá của mạng là mảng hai chiều A có N dòng và N cột, mà giá
trị phần tử A[i, j] chính là ñơn giá từ máy i sang máy j.
Câu 1: Cho trước một mạng, hãy kiểm ra tính an toàn của mạng ñó.
Câu 2: Khi mạng không an toàn ñược phép bổ sung một số kênh truyền ñể
nó trở thành an toàn. ðơn giá mỗi kênh truyền bổ sung theo ñược coi bằng hai lần
giá trị cực ñại ñơn giá các kênh ñã có. Mọi kênh bổ sung ñược coi có ñơn giá như
nhau. Hãy tìm cách bổ sung các kênh mới mà ñơn giá mạng là nhỏ nhất.
Câu 3: Khi mạng an toàn hoặc sau khi bổ sung kênh ñể mạng an toàn, hãy in
ra ñơn giá mạng và ma trận ñơn giá.
Dữ liệu vào: cho trong file INP.B2 với cấu trúc như sau:
Dòng ñầu tiên ghi 2 số n, m cách nhau bởi dấu cách.
Mỗi dòng thứ i trong số m dòng tiếp theo ghi thông tin về kênh nối thứ i của
mạng gồm 3 số d[i], c[i], g[i] trong ñó d[i], c[i] là chỉ số của hai máy tương ứng với
kênh này và g[i] (nguyên dương) là chi phí ñể truyền một ñơn vị thông tin từ máy
d[i] ñến máy c[i] theo kênh này. Các giá trị g[i] cho trước không vượt quá 40 (và
như vậy ñơn giá các kênh bổ sung không vượt quá 80).
Kết quả: ghi ra file OUT.B2 theo qui cách sau:
Dòng ñầu tiên ghi 1 số nguyên p thể hiện mạng có an toàn hay không và p có ý
nghĩa là số lượng kênh cần bổ sung. p=0 có nghĩa mạng an toàn; p>0 có nghĩa mạng
không an toàn và cần bổ sung p kênh nữa ñể mạng an toàn với chi phí bổ sung ít
nhất.
p dòng tiếp theo ghi p kênh bổ sung. Cách ghi như trong file dữ liệu vào.
Dòng tiếp theo ghi ñơn giá của mạng an toàn.
N dòng tiếp theo ghi ma trận ñơn giá của mạng an toàn: mỗi hàng của ma
trận ghi trên một dòng.
Bài tập 3: Xây dựng ñường ống nước
Có 1 trạm cấp nước và N ñiểm dân cư. Hãy xây dựng chương trình thiết kế tuyến
ñường ống nước cung cấp ñến mọi nhà sao cho tổng chiều dài ñường ống phải dùng
là ít nhất. Giả sử rằng các ñường ống chỉ ñược nối giữa 2 ñiểm dân cư hoặc giữa
trạm cấp nước với ñiểm dân cư.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 58
Bài 8: Thảo luận về cài ñặt thuật toán tìm cây khung nhỏ nhất trên ñồ thị Mục tiêu
- Cài ñặt ñược thuật toán xây dựng tập các chu trình cơ bản.
- Cài ñặt ñược thuật toán Prim, Kruskal ñể ñưa ra cây khung nhỏ nhất của ñồ thị cho
trước.
- Mở rộng ý tưởng, mở rộng thuật toán Prim.
- Cài ñặt ñược thuật toán xây dựng tập các chu trình cơ bản.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
- Rèn luyện tư duy sáng tạo.
a. Nhắc lại lý thuyết
b. ðề bài tập
Bài 1 Tìm cây bao trùm nhỏ nhất của ñồ thị G dung thuật toán Kruskal
Bài 2 Tìm cây bao trùm nhỏ nhất của ñồ thị G dung thuật toán Prim
c. Hướng dẫn giải
Bài 1 ðề bài : Tìm cây bao trùm nhỏ nhất của ñồ thị G
Phân tích bài toán :
Trước hết ta phải xét ví dụ sau:
8 3
2
1 7 2 3 7
5
1 8
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 59
2 1
4 1 7 6
6 1 9
Tư tưởng của thuật toán là ñưa từng cạnh vào cây bắt ñầu từ những cạnh có trọng số
nhỏ nhất và làm cho ñến khi cây bao gồm tất cả các ñỉnh của ñồ thị.
Giả sử T là cây bao trùm cần tìm. Và tập V là tập bao gồm các tập Gi có tính chất
như sau:
- Gi có phần tử là các ñỉnh của ñồ thị mà chúng ñược nối với nhau bởi các cạnh ñã
ñược ñưa vào T. Từ một ñỉnh thuộc Gi luôn có ñường ñi ñến một ñỉnh khác cũng
thuộc Gi.
- Giao của Gi và GJ bẵng rỗng.
Với ñịnh nghĩa như trên ta nhận thấy rõ ràng rằng mỗi một tập Gi thuộc tập V là
một cây bao trùm con nhỏ nhất. Như vậy thuật toán của chúng ta như một bài toán
quy nạp là gộp nhưng cây bao trùm này thành những cây trùm lớn hơn cho ñến khi
nó gồm tất cả các ñỉnh của ñồ thị và ñương nhiên ta phải nối những cây bao trùm Gi
này bằng những cạnh có trọng số nhỏ nhất. Kết thúc khi V = { {1,2,3…,n} } = {X};
Ban ñầu:
+ Cây bao trùm của ñồ thị là rỗng nghĩa là chưa có cạnh nào ñược ñưa vào cây bao
trùm. (T = ỉ ).
+ Gi chính là những ñỉnh của ñồ thị => V = { {1}, {2}, {3}…,{n} }
Thuật toán ñược viết cụ thể với ví dụ trên như sau:
- Khởi tạo T = { }
V = { {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} }
- ðưa cạnh nhỏ nhất (1,2) vào cây khi ñó 1 ñược nối với 2 nên thay {1} và {2}
trong V bằng {1,2}
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 60
T = { (1,2) }
V = { {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} }
- ðưa cạnh (4,5) vào cây:
T = { (1,2); (4,5)}
V = { {1,2}, {3}, {4,5}, {5}, {6}, {7}, {8}, {9} }
- ðưa cạnh (5,6) vào cây:
T = {(1,2); (4,5); (5,6)}
V = { {1,2}, {3}, {4,5,6}, {7}, {8}, {9} }
- ðưa cạnh (6,9) vào cây:
T = {(1,2); (4,5); (5,6); (6,9)}
V = { {1,2}, {3}, {4,5,6,9}, {7}, {8} }
- ðưa cạnh (1,4) vào cây:
T = {(1,2); (4,5); (5,6); (6,9); (1,4)}
V = { {1,2,4,5,6,9}, {3}, {7}, {8} }
- ðưa cạnh (5,7) vào cây:
T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7)}
V = { {1,2,4,5,6,9}, {3}, {8} }
- ðưa cạnh (3,5) vào cây:
T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7); (3,5)}
V = { {1,2,3,4,5,6,7,9}; {8} }
- ðưa cạnh (7,8) vào cây:
T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7); (3,5); (7,8)}
V = { {1,2,3,4,5,6,7,8,9} }
Kết thúc vì V = {X};
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 61
Chú ý: Thứ tự chọn các cạnh ñưa vào cây là ưu tiên các cạnh có trọng số bé hơn.
Cấu trúc dữ liệu
Ta biểu diễn ñồ thị dưới dạng liệt kê các cung (chỉ áp dụng cho ñồ thị nhỏ)
Như vậy dung một mảng hai chiều:
e: array [1…Emax, 1..3] of Integer
với e [i,3] là trọng số của cung (e[i,1], e[i,2],…,emax)
Mảng T: array [1…Emax, 1..2] of Integer biểu diễn các cạnh ñược ñưa vào T.
Dùng biến solT ñể xác ñịnh số lượng cạnh ñã ñưa vào cây T;
(khởi tạo solT: = 0 nghĩa là cây T = ỉ)
Biểu diễn V là tập hợp của các tập hợp rất phức tạp, do ñó ta dùng một Cấu trúc dữ
liệu ñơn giản ñể mô phỏng tập V như sau:
Mảng tap V: array[1…Nmax] of integer
Trong ñó hai ñỉnh i và j thuộc cùng một tập Gk nào ñó nếu như tap V[i] = tap [j]
Như vậy ban ñầu giá trị của mảng tapV là tapV[i] gán bằng i;
ở mỗi bước khi ta ghép các ñỉnh của 2 tập Gk và Gh thành một tập thì ta chỉ việc gán
cả các giá trị của tập Gk bằng giá trị của tập Gh.
Ví dụ với N = 10;
ở một bước nào ñó
mảng tapV = [ 1,2,2,6,6,2,1,4,4,10]
ta hiểu là V = { {1,7}; {2,3,6}, {4,5}, {8,9}, {10} }
ñến bước tiếp theo ta ñưa cạnh (4,6) vào cây nghĩa là cần gộp 2 tập {2,3,6 }và {4,5}
thành một. Ta gán tapV[4] = tapV[2;]
tapV[5] = tapV[2;];
Khi ñó mảng tapV = [1,2,2,2,2,2,1,4,4,10]
ðiều này rất có lợi khi ta gộp hai tập hợp con với nhau.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 62
Với toàn bộ dữ liệu ñược mô tả như trên ta có phần cài ñặt chương trình:
Chương trình minh họa :
Program kruskal;
Const Nmax = 100;
Emax = 1000;
Type mangcanh = array [1..Emax, 1..2] of integer;
Dinh = array [1…Nmax] of integer;
Var e,T; Mangcanh;
TapV: Dinh;
N, solE, solT: integer;
(*solE là số cạnh của ñồ thị còn solT là số cạnh ñược ñưa vào T*)
Prrocudure Doctep;
(* Dữ liệu vào gồm có:
- Dòng ñầu tiên chứa số N
- Từ dòng thứ hai trở ñi mỗi dòng chứa 3 số nguyên là 2 ñỉnh của một cạnh và trọng
số của cạnh ñó.
*)
Var f: text;
i,j,k: integer;
Begin Assign (f’, cung.txt’); Reset(f);
Readln (F,N);
SolE: = 0;
While not eof(f) do
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 63
begin Read (f,i,j,k);
Inc(solE);
e[solE,1]: = i;
e[solE,2]: = j;
e[solE,3]: = k;
End;
Close (f);
End;
Procedure Sapxep;
(*Dùng phương pháp sắp xếp nổi bọt ñể sắp xếp các cạnh theo thứ tự trọng số từ
nhỏ tới lớn(*)
Var ij : integer;
Beign
For i:= 1 to solE-1 do
For j:= i + 1 to solE do
If e[i,3] > e[j,3] then
Doicho(i,j);
End;
Procedure Doicho (i,j;integer);
Var temp: integer;
Begin
Temp: = e[i,1];
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 64
e[i,1]: = e[j,1];
e[j,1]: Temp;
Temp: = e[i,2];
e[i,2]: = e[j,2];
e[j,2]: = Temp;
Temp: = e[i,3];
e[i,3]: = e[j,3];
e[j,3]: = Temp;
End;
Procedure TimCay:
Var i,k, temp:integer;
Begin
solT: = 0; (*T = ỉ*)
For i: = 1 to N do
TapV [i]: = i;
K: = 0;
While (not KttapV) and (K<solE) do
(*Chừng nào tapV còn chưa ñồng nhất các giá trị *)
Begin
Inc (k);
(*ðưa cung thứ k vào cây T*)
If tapV [e,k,1] <> tapV [e [k,2] ] then
(* Nếu 2 ñỉnh e[k,l] và e[k,2] chưa thuộc cùng 1 cây con thì ta mới ñưa vào cây T
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 65
và thực hiện tiếp. Ngược lại thì bỏ qua cạnh này ñể tránh tạo thành chu trình trong
cây*)
Begin
Inc(solT);
T [solT,1]: = e[k,1];
T [solT,2]: = e[k,2];
(* ðồng nhất giá trị trong 2 tập con chứa 2 ñỉnh e[k,1] và e[k,2] của V*). ðưa cạnh
vào cây khung.
temp: = tapV [ e[k,2] ];
For i: = 1 to N do
If tapV [i] = temp then
TapV [i]: = TapV [ e[i,2] ];
End;
End;
End;
Function KTtapV: Boolean;
(*Hàm kiểm tra xem các giá trị của tập V có bằng nhau hay không*)
Var i: integer;
Begin KTtapV: = True;
For i: = 2 to N do
If tapV [i] <> tapV [i] then
Begin KTtapV: = False;
Exit;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 66
End;
End;
Procedure GhiTep;
(*Ta chỉ việc ñưa cây T ra màn hình*)
Var i: integer;
begin
Writeln (‘ Cac cung thuoc cay bao trum nho nhat T la:’)
For i: = 1 to solT do
Writeln (T [i, l]; ‘ ‘; T[i,2];
Readln;
End;
BEGIN
DocTep;
Sapxep;
TimCay;
GhiTep;
END.
Bài 2 ðề bài : Tìm cây bao trùm nhỏ nhất của ñồ thị G
Phân tích bài toán :
Giả sử T là cây bao trùm tối thiểu cần xây dựng. Giả xử ta bắt ñầu từ ñỉnh u.
Gọi U là tập các ñỉnh kề với các ñỉnh có cung nối với cây T;
Khởi tạo U = u;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 67
T = ỉ;
B1: Chọn (u,v) là cạnh có trọng số bé nhất với u
B2: ðưa ñỉnh v vào tập U;
B3: Nếu U = X thì kết thúc; ngược lại thì quay lại bước 1;
Cấu trúc dữ liệu
Ta biểu diễn ñồ thị dưới dạng liệt kê các cung (chỉ áp dụng cho ñồ thị nhỏ)
Như vậy dung một mảng hai chiều:
e: array [1…Emax, 1..3] of Integer
với e [i,3] là trọng số của cung (e[i,1], e[i,2],…,emax)
Mảng T: array [1…Emax, 1..2] of Integer biểu diễn các cạnh ñược ñưa vào T.
Dùng biến solT ñể xác ñịnh số lượng cạnh ñã ñưa vào cây T;
(khởi tạo solT: = 0 nghĩa là cây T = ỉ)
Biểu diễn V là tập hợp của các tập hợp rất phức tạp, do ñó ta dùng một Cấu trúc dữ
liệu ñơn giản ñể mô phỏng tập V như sau:
Mảng tap V: array[1…Nmax] of integer
Trong ñó hai ñỉnh i và j thuộc cùng một tập Gk nào ñó nếu như tap V[i] = tap [j]
Như vậy ban ñầu giá trị của mảng tapV là tapV[i] gán bằng i;
ở mỗi bước khi ta ghép các ñỉnh của 2 tập Gk và Gh thành một tập thì ta chỉ việc gán
cả các giá trị của tập Gk bằng giá trị của tập Gh.
Ví dụ với N = 10;
ở một bước nào ñó
mảng tapV = [ 1,2,2,6,6,2,1,4,4,10]
ta hiểu là V = { {1,7}; {2,3,6}, {4,5}, {8,9}, {10} }
ñến bước tiếp theo ta ñưa cạnh (4,6) vào cây nghĩa là cần gộp 2 tập {2,3,6 }và {4,5}
thành một. Ta gán tapV[4] = tapV[2;]
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 68
tapV[5] = tapV[2;];
Khi ñó mảng tapV = [1,2,2,2,2,2,1,4,4,10]
ðiều này rất có lợi khi ta gộp hai tập hợp con với nhau.
Tập U là tập các ñỉnh có cung nối với T, khai báo T,X: set of 1…Nmax;
Các thành phần dữ liệu khác khai báo giống như phần trước.
Program Prim;
Const Nmax = 100;
Emax = 1000;
Type mangcanh = array [1…Emax, 1...3]of integer;
Tap = set of 1…Nmax;
Var e,T: Mangcanh;
VT X: Tap; {X: Tập ñỉnh của ñồ thị; VT: Tập ñỉnh của cây}
N, solE, solT: integer;
(*Thủ tục ñọc file và ghi file tương tự như trên*)
Procedure Timcay;
Var k,i,j: integer;
TrongsoMin: Longint;
Begin
solT: = 0; VT = [xp]
X: = [ ];
For i: = 1 to N do
X: = X + [i];
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 69
REPEAT
(*Tìm cạnh (u,v) sao cho u và có trọng số nhỏ nhất *)
TrongsoMin: = MaxLongint;
For k: = 1 to solE do
Begin
If (e[k,l] in VT and not e[k,2] in VT and (e[k,3] < TrongsoMin)
then
Begin
i: = e[k,1];
j: = e[k,2];
TrongsoMin: = e[k,3;
End;
If not e[k,1] in VT and (e[k,2] in VT and (e[k,3] < TrongsoMin)
then
Begin
i: = e[k,2];
j: = e[k,1];
TrongsoMin: = e[k,3];
End;
(*ðưa j vào tập U*)
vT = VT + [j];
(*ðưa cạnh (i,j) vào cây T*)
inc(solT);
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 70
T [solT,1]: = i;
T [solT,2]: = j;
UNILT U = X;
End;
BEGIN
Docfile;
Timcay;
Ghifile;
END.
d. Bài tập tự giải
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 71
Bài 9, 10: Bài toán tìm ñường ñi ngắn nhất Mục tiêu
Mục tiêu của bài này người học có khả năng:- Biểu diễn ñồ thị trên máy tính bằng
các phương pháp khác nhau.
- Áp dụng ñược thuật toán ford-bellman và dijkstra tìm ñường ñi ngắn nhất ứng với
một ñồ thị xác ñịnh. Cài ñặt ñược thuật toán.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
Thuật toán dijkstra với ý tưởng “lan tỏa” và lưu 1 chỉ số tại mỗi ñỉnh.
ðể tìm lại ñường ñi ngắn nhất, ta lưu cả tên ñỉnh liền kề trước nó trên ñường ñi
ngắn nhất.
b. ðề bài tập
Bài tập 1: Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung).
Áp dụng thuật toán Dijkstra tìm ñường ñi ngắn nhất từ ñỉnh 5 tới các ñỉnh còn lại
cho ñồ thị sau:
Bài2 Tìm ñường ñi ngắn nhất từ 1 ñến các ñỉnh còn lại của ñồ thị
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 72
Bài 3 ðưa thư
Nhà bác ñưa thư có việc bận, bác ñưa thư rất sốt ruột muốn về nhà ngay
nhưng bác phải ñưa một thư quan trọng cho anh B ở quận Ba ðình. Hiện tại
bác ở quận Thanh Xuân. ðường ñi từ chỗ bác tới nhà anh B phải ñi qua một số
quận huyện khác với khoảng cách giữa các quận như sau. Hãy giúp bác ñưa
thư tìm ñường ñi ngắn nhất với thời gian ít nhất ñể bác có thể về nhanh chóng
giải quyết công việc gia ñình.
Bài 4 Hổ bắt mồi
Một con hổ ñứng trên ñồi cao nhìn xuống khu rừng và phát hiện ra 5 con mồi
ở 5 vị trí khác nhau. Con hổ muốn bắt con Nai trong số 5 con vật ñó là Nai, Gà,
Hươu, Thỏ, Bò ñể ăn thịt. Khi con Hổ muốn bắt con Nai ñó, nó phải chạy qua
ñường mà 4 con vật còn lại ñang ñứng. Vị trí và khoảng cách mà các con vật
ñược biểu diễn như sau. Tìm ñường ñi ñể quãng ñường mà con Hổ phải chạy
là ngắn nhất ñể bắt ñược con Nai.
Bài 5 Mèo bắt chuột
Mèo Tom(1) rình chú chuột nhỏ Jeny(4) ñang ăn trộm phomat. Từ chỗ Tom ñến
Jeny có cái xô nước(2), chậu cây cảnh (3), ghế sofa(5) với thời gian ñể Tom chạy
ñến các ñồ vật trên và giữa các ñồ vật cũng như thời gian Tom chạy từ các ñồ vật
ñến Jeny như sau: xô nước chậu cây cảnh
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 73
Tom Jeny
ghế sofa
Tom có thể chạy ñến nấp ở chỗ các ñồ vật trên ñể rình và bắt Jeny. Tìm thời gian
nhỏ nhất ñể Tom chạy ñến bắt Jeny mà không bị Jeny phát hiện(nhờ nấp vào các ñồ
vật có trên ñường ñi)
Bài 6 Cho ñồ thị có trọng số G = (X,E). Tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và
kết thúc của ñồ thị
c. Hướng dẫn giải
Bài 1:
Biểu diễn ñồ thị dạng ma trận kề như sau:
0 18 M 13 12
18 0 11 3 M
M 11 0 5 9
13 3 5 0 4
12 M 9 4 0
Dùng thuật toán Dijkstra giảm trọng số 1 lần tại mỗi ñỉnh ta có:
Kí hiệu:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 74
D[i] : Chỉ số tại ñỉnh i (Tổng trọng số từ ñỉnh xuất phát tới ñỉnh i, ñược cập nhật
theo từng bước của thuật toán)
T[i] : Tên ñỉnh kề ngay trước ñỉnh i trên ñường ñi ngắn nhất ñược cập nhật theo
từng bước của thuật toán
Bước ðỉnh 5
ñược
chọn
Các ñỉnh
chưa xét
D[1],T[1] D[2],T[2] D[3],T[3] D[4],T[4]
Khởi tạo
1
2
3
4
5
4
2
3
1
1,3,4,2
1,3,2
1,3
1
12,5
12.5
12,5
12,5
12,5
∞
7,4
7,4
7,4
7,4
9,5
9,5
9,5
9,5
9,5
4,5
4,5
4,5
4,5
4,5
Trong ñó, bước khởi tạo ñược cho trong dòng ñầu tiên.
Thực hiện bước 1, trong D[v], với v=1, 2, 3, 4 ở dòng ñầu tiên, thì D[4 ]
= 4 là nhỏ nhất nên ñỉnh 4 ñược chọn. Ta xác ñịnh lại các D[v] cho các ñỉnh còn lại
1, 2 và 3. Chỉ có D[2] là nhỏ ñi và D[2] = 7, vì D[4] + c(4,2) = 4 + 3 = 7 < ∞.
Tiếp tục thực hiện các bước 2, 3, 4 ta thu ñược ñộ dài ñường ñi ngắn nhất từ
ñỉnh 0 tới các ñỉnh 1, 2, 3, 4 ñược cho ở dòng cuối cùng trong bảng, chẳng hạn ñộ
dài ñường ñi ngắn nhất từ 5 tới 2 là D[2] = 7 và ñó là ñộ dài của ñường ñi 5�4�2.
Bài2 Tìm ñường ñi ngắn nhất từ 1 ñến các ñỉnh còn lại của ñồ thị
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 75
Kết quả tính toán theo thuật toán ñược trình bày theo bảng dưới ñây: Quy ước viết
hai thành phần của nhãn theo thứ tự d[v]. ðỉnh ñược ñánh dấu * là ñỉnh ñược chọn ñể
cố ñịnh nhãn ở bước lặp ñang xét, nhãn của nó không biến ñổi ở các bước tiếp theo, vì
thế ta ñánh dấu (-).
Bước lặp ðỉnh 1 ðỉnh 2 ðỉnh 3 ðỉnh 4 ðỉnh 5 ðỉnh 6
Khởi 0, 1 1, 1* ∞, 1 ∞, 1 ∞, 1 ∞, 1
1 - - 6, 2 3, 2* ∞, 1 8, 2
2 - - 4, 4* - 7, 4 8, 2
3 - - - 7, 4 5, 3*
4 - - - 6, 6* -
Bài 3 Nhà bác ñưa thư có việc bận, bác ñưa thư rất sốt ruột muốn về nhà ngay
nhưng bác phải ñưa một thư quan trọng cho anh B ở quận Ba ðình. Hiện tại bác ở
quận Thanh Xuân. ðường ñi từ chỗ bác tới nhà anh B phải ñi qua một số quận
huyện khác với khoảng cách giữa các quận như sau
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 76
Hãy giúp bác ñưa thư tìm ñường ñi ngắn nhất với thời gian ít nhất ñể bác có thể về
nhanh chóng giải quyết công việc gia ñình.
*Phân tích bài toán: Bác ñưa thư cần chuyển thư từ quận Thanh Xuân tới Quận Ba
ðình nhưng lại không có ñường ñi trực tiếp từ quận Thanh Xuân tới quận Ba ðình
mà phải ñi qua một số quận khác. Với ñiểm xuất phát là quận Thanh Xuân tìm các
con ñường có thể ñi tới quận Ba ðình và tính khoảng cách giữa hai quận ñó khi ñi
qua các con ñường khác nhau.
Ta tính khoảng cách từ Quận Thanh Xuân (Q.TX) tới các Q.Thanh Trì (Q.TT),
Q.Hoàng Mai (Q.HM), Q.Tây Hồ (Q.TH), Q.Hà ðông (Q.Hð). Ta thấy không có
ñường ñi trực tiếp từ Q.Thanh Xuân ñến Q.Hà ðông, nên còn 3 sự lựa chọn là ñi
qua Q.TT, Q.HM và Q.TH. Ta có khoảng cách tương ứng là:
Q.TX � Q.TT = 1km;
Q.TX � Q.HM = 7km;
Q.TX � Q.TH = 6km;
NX: Quãng ñường từ Q.TX ñến Q.TT ngắn nhất với 1km. Vậy ta sẽ chọn và ñánh
dấu lối ñi này.
Tiếp tục tính ñường ñi từ Q.TT ñến Q.HM, Q.TH, Q.H ð và Q.B ð. Ta có:
Q.TT � Q.HM = ∞;
Q.TT � Q.TH = 3km;
Q.TT � Q.Hð = 4km;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 77
Q.TT � Q.Bð = 1km;
NX: Quãng ñường từ Q.TT ñến Q.Bð là ngắn nhất 1km và là ñích của chuyến ñi.
Vậy tổng khoảng cách từ Q.TX � Q.Bð là 1+1=2km.
Giả sử các ñỉnh 1,2,3,4,5,6 tương ứng với các quận Thanh Xuân, Hoàng Mai, Tây
Hồ, Thanh Trì, Hà ðông và quận Ba ðình. Ta có ñồ thị sau:
Tìm ñường ñi ngắn nhất từ quận Thanh Xuân tới Ba ðình là tìm ñường ñi ngắn
nhất giữa từ ñỉnh 1 tới ñỉnh 6 của ñồ thị trên. Áp dụng thuật toán Dijkstra ta có bảng
sau:
1 2 3 4 5 6
Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞ 1,∞
1 ---- 1,7 1,6 1,1* ---- ----
2 ---- ---- 4,4 ---- 4,5 4,2*
3 ---- ---- ----* ---- 6,4 ----
4 ---- ---- ---- ---- ----* ----
Từ bảng trên ta thấy con ñường ngắn nhất ñể ñi từ ñỉnh 1 tới ñỉnh 6 là 1� 4 � 6
với trọng số là 2, nói cách khác bác ñưa thư có thể ñi từ quận Thanh Xuân tới quận
Thanh Trì và tới quận Ba ðình với quãng ñường là 2km.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 78
Bài 4 Một con hổ ñứng trên ñồi cao nhìn xuống khu rừng và phát hiện ra 5 con mồi
ở 5 vị trí khác nhau. Con hổ muốn bắt con Nai trong số 5 con vật ñó là Nai, Gà,
Hươu, Thỏ, Bò ñể ăn thịt. Khi con Hổ muốn bắt con Nai ñó, nó phải chạy qua
ñường mà 4 con vật còn lại ñang ñứng. Vị trí và khoảng cách mà các con vật ñược
biểu diễn như sau. Tìm ñường ñi ñể quãng ñường mà con Hổ phải chạy là ngắn nhất
ñể bắt ñược con Nai.
*Phân tích bài toán: Con hổ không thể bắt ñược tất cả 5 con vật ñó, và nó chỉ có thể
chọn 1. Trong các con ñường ñể ñi ñến chỗ con Nai mà nó muốn bắt ñó, có những
con ñường dài và ngắn khác nhau. Nó phải tính toán sao cho quãng ñường chạy ñến
con Nai ñó là ngắn nhất ñể ñề phòng con vật ñó nhìn thấy từ xa và bỏ chạy.
Gọi vị trí Hổ, Bò, Thỏ, Hươu, Nai tương ứng là 1,2,3,4 với các ñỉnh của ñồ thị sau:
ðể ñi từ 1 ñến 5 ta tính khoảng cách từ 1 ñến các ñỉnh còn lại:
1 � 2 = 4
1 � 3 = ∞
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 79
1 � 4 = ∞
1 � 5 = ∞
Ta thấy có ñường ñi duy nhất là 1�2.
Tiếp tục tính khoảng cách từ 2 � 3, 4, 5 ta có:
2 � 3 = 10
2 � 4 = 2
2 � 5 = 8
NX: Quãng ñường 2 � 4 là nhỏ nhất. ðánh dấu và chọn con ñường này.
Khi chọn ñường ñi, nếu ñường nào ñã ñược chọn và ñánh dấu sẽ không ñược xét lại
nữa. Vậy còn lại 2 ñỉnh chưa xét là 3 và 5, nhưng không có ñường ñi trực tiếp từ 4
� 3, chỉ còn ñường 4 � 5 với khoảng cách là 1km và là mục ñích của bài toán.
KL: ðường ñi ngắn nhất từ 1 � 5 là 1 � 2 �4 � 5 với khoảng cách là 1+4+2=7
Áp dụng thuật toán Djstral ta có bảng sau:
1 2 3 4 5
Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞
1 ---- 1,4* ---- ---- ----
2 ---- ---- 2,14 2,6* 2,12
3 ---- ---- ---- ---- 4,7*
4 ---- ---- ---- ---- ----
Nhìn vào bảng trên ta thấy ñường ñi ngắn nhất từ 1 ñến 5 là 1 - 2 - 4 - 5 với trọng số
là 7.
Nói cách khác con Hổ muốn bắt và ăn thịt con Nai thì Hổ phải ñi qua chỗ con Bò và
con Hươu.
Bài 5
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 80
Mèo Tom(1) rình chú chuột nhỏ Jeny(4) ñang ăn trộm phomat. Từ chỗ Tom ñến
Jeny có cái xô nước(2), chậu cây cảnh (3), ghế sofa(5) với thời gian ñể Tom chạy
ñến các ñồ vật trên và giữa các ñồ vật cũng như thời gian Tom chạy từ các ñồ vật
ñến Jeny như sau: xô nước chậu cây cảnh
Tom Jeny
ghế sofa
Tom có thể chạy ñến nấp ở chỗ các ñồ vật trên ñể rình và bắt Jeny. Tìm thời gian
nhỏ nhất ñể Tom chạy ñến bắt Jeny mà không bị Jeny phát hiện(nhờ nấp vào các ñồ
vật có trên ñường ñi)
Bài làm:
Giả sử vị trí các ñối tượng tương ứng với các ñỉnh 1, 2, 3, 4, 5 của ñồ thị sau:
Phân tích tương tự như 2 bài toán trên ta sẽ tìm ñược con ñường cần tìm
Áp dụng thuật toán Dijkstra ñể tìm ñường ñi ngắn nhất từ 1 � 4
1 2 3 4 5
Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞
1 ---- 1,3* ---- ---- 1,12
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 81
2 ---- ---- 2,8 ---- 2,7*
3 ---- ---- ---- 5,15* ----
4 ---- ---- ---- ---- ----
Dựa vào bảng trên ta có con ñường ngắn nhất là 1 – 2 – 5 - 4 với thời gian là 15
Bài 6 Cho ñồ thị có trọng số G = (X,E). Tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và
kết thúc của ñồ thị.
Phân tích bài toán :
Phương pháp 1: Tại mỗi ñỉnh thực hiện việc giảm trọng số nhiều lần.
Bài toán này cũng dùng mảng truoc ñánh dấu các ñỉnh trên ñường ñi như trên và
dùng cấu trúc hàng ñợi.
Có một ñiểm mới là nó cần thêm một mảng trongso: array[1…Nmax] of <type
trongso> (tuỳ vào bài toán <type trong so> có thể là kiểu real hoặc kiểu longint).
Trongso[i] bằng tổng trọng số của các cung nằm trên ñường ñi tính từ ñỉnh xp cho
ñến i. Bài toán của chúng ta trở thành tìm mảng trongso[i] sao cho nó ñạt giá trị
nhỏ nhất.
Thuật toán của phần này rất giống thuật toán duyệt chiều rộng nhưng cải tiền một
chút là có gắn thêm mảng trọng số.
Khi duyệt các ñỉnh kề của một ñỉnh u vừa lấy ra khỏi hành ñợi, gặp một ñỉnh i kề
với u ta không cần biết truoc[i] là ñỉnh nào, mà ta chỉ quan tâm ñường ñi từ u ñến i
có ngắn hơn ñường cũ không (trongso[i]???trongso [u] +a[u,i].
Trongso [i] chính là ñường ñi cũ ñến ñỉnh i, trongso [u] + a[u,i] là ñường ñi mới từ
ñỉnh u ñi ñến.
Nếu ñường mới ngắn hơn nghĩa là trongso[u] + a[u,i] <trongso [i] thì ta ghi nhận
ñường ñi mới, ta phải dán lại:
trongso [i] := trongso[u] + a[u,i];
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 82
truoc[i]:= u;
Thuật toán ñược trình bày cụ thể như sau:
Khởi tạo:
- Mảng trongso [i] = Maxlongint;
- Truoc [xp]: = -1;
- Khởi ñộng hàng ñợi và ñưa xp vào;
Thực hiện bước lặp.
REPEAT
- Lấy 1 ñỉnh khỏi hàng ñợi gắn vào biến u;
- Duyệt các ñỉnh i kề với u;
(Nếu ñường ñi mới ngắn hơn ñường ñi cũ thì thực hiện giảm trọng số cho i)
Nếu trongso[i]>trongso[u] +a[u,i] thì
+ trongso[i]:= trongso[u] + a[u,i];
+ truoc [i]:= u;
UNILT <hàng ñợi Q rỗng>;
Chương trình minh họa :
Program DIJSTRA_phuongphap1;
Const Nmax = 100;
Type MATRANKE = array[1…Nmax, 1…Nmax] of integer;
MANG = array [1…Nmax] of Longint;
Var a: MATRANKE;
q, duong, truoc, trongso: MANG;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 83
N, sold, xp, kt, qf, ql: Integer;
fifo: text:
(*fi: file input la tep doc du lieu vao
fo: file output la tep doc du lieu ra*)
Procedore Doctep;
Var i,j: integer;
Begin
Asign (fi,’matran:inp’); Reset(fi);
Readln (fi, N);
For i: = 1 to N do
For j: = 1 to N do
Read (fi, a[i,j]);
Readln (f,xp,kt);
Close (f);
End;
Procedure InitQ:
(*Thu tuc khoi dong hang doi *)
Begin
qf: = 0;
ql:= 1;
End;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 84
Procedure Put (u:integer);
(*Dua mot phan tu vao hang doi *)
Begin
Inc(ql);
q[ql]: = u;
End;
Function Get: Integer;
(*Ham lay mot phan tu ra khoi hang doi*)
Begin
Get:= q[qf];
inc [qf];
End;
Function Qempty: Boolean;
(*Ham kiem tra hang doi da rong hay chưa*)
Begin
Qempty:= (qf>ql);
End;
Procudure Dijstra
(*Thu tuc duyet Dijstra theo phuong phap 1: giam trong so nhieu lan*)
Var i, u: integer;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 85
Begin (*cac buoc khoi tao (giong trong phan thuat toan)*)
truoc[xp]:= -1;
Fullhar(…) = For i:= 0 to N do Trongso[i]:= MaxLongint;
Trongso[xp]:= 0;
InitQ;
Put(xp);
(*Bat dau vong lap*)
REPEAT
(*Lay mot dinh khoi hang doi gan vao bien u*)
u:= Get;
For i:= 1 to N do
(*Duyet tat ca cac dinh i cua do thi*)
If (a[u,i]>=0) and (trongso [i]>trongso [u] + a[u,i]then
(*Neu dinh i ke voi u va duong di cu lon hon duong di moi
thi:*)
Begin (*Gan lai gia tri duong di moi*)
trongso [i]:= trongso [u] +a[u,i];
(*danh dau duong di moi den i qua dinh truoc do la u*)
truoc [i]:= u;
Put(i);
End;
UNILTQempty: (*Ket thuc khi khong di duoc nua*)
End;
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 86
Procedure Timnguoc;
Var u:integer;
Begin
sold:= 0; (*Mảng ñường rỗng*)
(*Ban ñầu gán u bằng kt*)
u:= kt;
Repeat
(*Với mỗi bước lặp ghi u vào mảng duong*)
Inc(sold);
duong[sold]:= u;
(*Muốn ñến bước tiếp theo phải gắn u = truoc [u]*)
u:= truoc[u];
Unilt u = -1; (*Ket thuc khi u:= -1 do luc truoc ta gan truoc [xp]= -1).
End;
procedure Ghitep:
Var ij:integer;
Begin
Asign (fo, ‘kq.out’); Rewrite (fo);
If truoc [kt] <> 0 then
Begin Timnguoc;
For i:= sold downto 1 do
Write (fo, duong [i], ‘ ‘)’
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 87
End else
Writeln (f,0);
Close (fo);
End;
BEGIN
Doctep;
Dijstra;
Ghitep;
END.
Phương pháp 2: Giảm trọng số 1 lần tại mỗi ñỉnh.
ðể làm rõ thuật toán này ta xét ví dụ cụ thể sau:
G= (X,E) ñưa ra hình vẽ
Mảng ma trận trọng số như sau:
3
5
1 4
2 6
7
Ta tìm ñường ñi bắt ñầu từ ñỉnh 1.
-1 1 2 5 -1 -1 -1
1 -1 -1 3 -1 -1 -1
2 -1 -1 7 -1 -1 -1
5 3 7 -1 5 -1 13
-1 -1 -1 5 -1 2 -1
-1 -1 -1 -1 2 -1 6
-1 -1 -1 13 -1 6 -1
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 88
Các bước thực hiện của thuật toán ñối với ví dụ này như sau:
(M = MaxLongint). Trình tự thực hiện ở mỗi bước từ trái sang phải.
Bước
ðỉnh có
trọng số
nhỏ nhất
trong B
Tập A Tập B Mảng trongso Mảng Truoc
B1 [1] [2,3,4,5,6,7] [0,M,M,M,M,M,M] [-1,0,0,0,0,0,0,]
B2 [1] [2,3,4,5,6,7] [0,1,2,5,M,M,M] [-1,1,1,1,0]
B3 2 [1,2] [3,4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0]
B4 3 [1,2,3] [4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0]
B5 4 [1,2,3,4] [5,6,7] [0,1,2,4,8,M,17] [-1,1,1,2,4,0,4]
B6 5 [1,2,3,4,5] [6,7] [0,1,2,4,8,10,17] [-1,1,1,2,4,5,4]
B7 6 [1,2,3,4,5,6] [7] [0,1,2,4,8,10,16] [-1,1,1,2,4,5,6]
B8 7 [1,2,3,4,5,6,7] [] nt Nt
B9 Kết thúc
Bài toán này cũng dùng mảng trước ñánh dấu các ñỉnh trên ñường ñi như trên
nhưng không dùng cấu trúc hàng ñợi.
Dùng một mảng trongso: array [1…Nmax] of <type trongso> (tuỳ vào bài toán
<type trongso> có thể là kiểu real hoặc kiểu longint).
Trongso [i] bằng tổng trọng số của các cung nằm trên ñường ñi từ ñỉnh xp cho ñến
i. Bài toán của chúng ta trở thành tìm mảng trongso [i] sao cho nó ñạt giá trị nhỏ
nhất.
Chia tập các ñỉnh của ñồ thị X thành 2 phần
a. Tập các ñỉnh có trọng số ñược gán cố ñịnh A.
b. Tập các ñỉnh có trọng số ñược gán tạm thời B.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 89
Trong suốt quá trình duyệt những ñỉnh ñược ñưa vào tập A thì trọng số của ñỉnh ñó
không thay ñổi và là ñộ dài ñường ñi ngắn nhất từ xp ñến nó, những ñỉnh ở tập B có
trọng số thay ñổi ñến khi nhỏ nhất thì ñược ñưa vào tập A. Cách thay ñổi trọng số
ñể nhỏ nhất ñược thể hiện như sau:
B1: Khởi tạo
Khởi tạo các giá trị của mảng trongso = Maxlongint (hoặc Maxreal)
Lập hai tập A và B. Ban ñầu A rỗng còn B = X
Duyệt tất cả các ñỉnh u kề với ñỉnh xp thì gán trongso [u] = a[u, xp] và truoc[u] =
xp;
REPEAT
B2: Tìm ñỉnh v thuộc tập B có trọng số nhỏ nhất.
ðưa ñỉnh v vào tập A (B/{v}; A + {v})
B3: Duyệt tất cả các ñỉnh i thuộc B mà kề với v
Nếu trongso[i]>trongso[v]+ a[i,v] thì
+ Gán lại trongso [i]:= trongso[v] + a[i,v];
+ ðồng thời gán truoc [i]:= v;
UNILT <B rỗng>;
Cấu trúc dữ liệu
Ma trận kề biểu diễn quan hệ của ñồ thị:
a(i;j) = -1 nếu i không nối với j
>= nếu i nối với j và a(a,j) là trọng số của cung 9i,j).
Mảng truoc và trongso ñược mô tả như trên.
Mảng duong ñể lưu các ñỉnh trên ñường ñi.
ðể biểu diễn tập A và B ta dùng kiểu tập hợp.
tap:set of <type tap>
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 90
Trong phần cài ñặt trên, khai báo tập A chỉ là minh hoà cho thuật toán còn trong bài
toán này không cần thiết phải sử dụng tập A, ta hiểu ngầm khi loại một phần tử khỏi
tập B thì nghĩa là ta ñã ñưa nó vào tập A.
Chương trình minh họa :
Program Difstra_Phuongphap2;
Const Nmax = 100;
Type Mang = array [0…Nmax] of Longint;
Tapcacdinh = set of a…Nmax;
Var a: array[1…Nmax, 1…Nmax] of integer;
duong, truoc, trongso: Mang;
N, sold, xp, kt: Integer;
tap A, tap B: set of Tapcacdinh;
(*Chỉ trình bày thủ tục Dijstra, các thủ tục khác tương tự như phần trên *)
Prcedure Dijstra;
Var i, u, v: integer;
Begin (*B1 khởi tạo các giá trị cần thiết *)
For i;= 0 to N do
Trongso [i]:= MaxLongint;
(*Khởi tạo tập B là tập tất cả các ñỉnh của ñồ thị*)
tapB: = [ ];
For i:= 1 to N do
tap B:= tapB +[i];
(*ðưa xp vào tập A*)
tapA:= [xp]
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 91
tapB: = tapB - [xp];
truoc[xp]:= -1;
(*Tìm các ñỉnh kề với xp gần trọng số và nhân cho những ñỉnh ñó*)
For i:= 1 to N do
if a [xp;i]>=0 then
Begin
trongso[i]:= a[xp,i];
truoc[i]:= xp
End;
REPEAT
(*Tìm ñỉnh v có trọng số nhỏ nhất trong tập B và ñưa vào tập A, loại khỏi tập
B*).
j: = Dinh_co_trong_so_min;
tapA:= tapA + [j];
tapB:= tapB + [j];
(*Tìm tất cả các ñỉnh thuộc B kề với ñỉnh v và thực hiện việc giảm trọng số
cho chúng*).
For i:= 1 to N do
If (i in tapB) and (a [i,j]>=0 and(trongso[i]>trongso[j] + a[i,j]) then
Begin
trongso [i]: = trongso[j] + a[i,j];
truoc[i]:= j;
End;
UNILT tapB = [ ];
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 92
End;
(*Hàm tìm ñỉnh có trọng số nhỏ nhất trong các ñỉnh thuộc tập B*)
Function Dinh_co_trong_so_min: Integer;
Var i,t: integer;
Begin tS [it]:= maxint
For i:= 1 to N do
If (i in tap B and (trongso[i] < trongso[t] then
t:=i;
Dinh_co_trong_so_+min:= t
End;
d. Bài tập tự giải
Bài tập 1: Áp dụng thuật toán Dijkstra tìm ñường ñi ngắn nhất cho ñồ thị sau:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 93
Bài tập 2: Di chuyển trên các hình tròn
Cho N hình tròn (ñánh số từ 1 ñến N). Một người muốn ñi từ hình tròn này
sang hình tròn khác cần tuân theo qui ước:
- Nếu khoảng cách giữa 2 ñiểm gần nhất của 2 hình tròn không quá 50 cm thì
có thể bước sang.
- Nếu khoảng cách này hơn 50cm và không quá 80cm thì có thể nhảy sang.
- Các trường hợp khác không thể sang ñược.
Một ñường ñi từ hình tròn này sang hình tròn khác ñuợc gọi là càng "tốt" nếu
số lần phải nhảy là càng ít. Hai ñường ñi có số lần nhảy bằng nhau thì ñường ñi nào
có số hình tròn ñi qua ít hơn thì ñường ñi ñó "tốt" hơn.
Các hình tròn ñược cho trong một file văn bản, trong ñó dòng thứ i mô tả
hình tròn số hiệu i (i = 1, 2,..., N) bao gồm 3 số thực: hoành ñộ tâm, tung ñộ tâm, ñộ
lớn bán kính (ñơn vị ño bằng mét).
Lập trình ñọc các hình tròn từ một file văn bản (tên file vào từ bàn phím), sau
ñó cứ mỗi lần ñọc số hiệu hình tròn xuất phát S và hình tròn kết thúc T từ bàn phím,
chương trình sẽ ñưa ra ñường ñi từ S ñến T là "tốt nhất" theo nghĩa ñã nêu (hoặc
thông báo là không có).
Yêu cầu ñường ñi ñược viết dưới dạng một dãy các số hiệu hình tròn lần lượt
cần ñược ñi qua trong ñó nói rõ tổng số các bước nhảy, tổng số các hình tròn ñi qua
và những bước nào cần phải nhảy.
Giới hạn số hình tròn không quá 100.
Bài tập 3: Tìm hành trình tốn ít xăng nhất
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 94
Trên một mạng lưới giao thông, một người muốn ñi từ ñiểm A ñến ñiểm B
bằng xe máy. Xe chứa ñược tối ña 3 lít xăng và chạy 100km hết 2,5 lít. Các trạm
xăng chỉ ñược ñặt ở các ñiểm dân cư, không ñặt ở giữa ñường và người này không
mang theo bất kỳ thùng chứa xăng nào khác. Hãy viết chương trình nhập vào mạng
lưới giao thông và xác ñịnh giúp người này tuyến ñường ñi từ A ñến B sao cho ít
tốn xăng nhất.
Bài tập 4: Di chuyển giữa các ñảo
Trên một ñảo quốc, có N hòn ñảo. Giả sử tất cả các ñảo ñều có hình dạng là
hình chữ nhật nằm ngang. Trên mỗi hòn ñảo có thể có sân bay nằm ở trung tâm ñảo,
có thể có cảng nằm ở 4 góc ñảo. Trên mỗi ñảo ñều có tuyến ñường xe buýt nối 4
góc ñảo với nhau và với trung tâm ñảo. Giữa 2 ñảo có thể ñi lại bằng máy bay nếu
cả 2 ñảo ñều có sân bay và có thể ñi lại bằng tàu nếu cả 2 ñảo ñều có cảng.
Giả sử rằng:
- Các tuyến ñường (bộ, không, thủy) ñều là ñường thẳng.
- Chi phí cho mỗi km và tốc ñộ của mỗi loại phương tiện là:
Phương tiện Tốc ñộ
(km/h)
Chi phí
(ñ/km)
Máy bay 1000 1000
Xe buýt 70 100
Tàu thủy 30 50
Hãy viết chương trình xác ñịnh tuyến ñường và cách di chuyển giữa 2 hòn
ñảo trong ñảo quốc sao cho:
- Thời gian di chuyển ít nhất.
- Chi phí di chuyển ít nhất.
- Thời gian di chuyển ít nhất nhưng với một số tiền chi phí không quá ð
ñồng.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 95
- Chi phí di chuyển ít nhất nhưng với thời gian di chuyển không vượt quá T
giờ.
Bài tập 5: Tìm ñường ngắn nhất
Giả sử X là tập các khu dân cư, U là tập các ñường sá nối liền các khu ñó. Ta
giả sử mọi chỗ giao nhau của các con ñường ñều thuộc X. Với con ñường u, số l(u)
là ñộ dài của u tính bằng km. Hãy chỉ ra tuyến ñường ñi từ một khu i sang khu j sao
cho tổng chiều dài là nhỏ nhất.
Bài tập 6: ðường ñi trên lưới
Cho 1 ma trận A[M, N], mỗi phần tử của nó chứa 1 số tự nhiên. Từ 1 ô (i, j)
ta có thể ñi sang ô kề nó (có chung 1 cạnh) nếu giá trị của ô kề này nhỏ hơn giá trị
lưu trong (i, j). Hãy tìm 1 ñường ñi từ ô (i, j) tới ô (k, l) trên ma trận sao cho phải ñi
qua ít ô nhất. Hãy tìm 1 ñường ñi từ ô (i, j) tới ô (k, l) trên ma trận sao cho tổng giá
trị các ô phải ñi qua nhỏ nhất.
Bài tập 7 : Tìm ñường với chi phí phải trả cho phép
Có N thành phố ñược ñánh số từ 1..N nối với nhau bằng các ñoạn ñường một
chiều. Mỗi ñoạn ñường bao gồm 2 thông số : ðộ dài và chi phí ñi của ñoạn ñường.
A sống tại thành phố 1 và A muốn di chuyển ñến thành phố N nhanh nhất có
thể.
Bạn hãy giúp A tìm ra ñường ñi ngắn nhất từ thành phố 1 ñến thành phố N
mà A có khả năng chi trả tiền.
Dữ liệu vào : ROADS.IN
- Dòng ñầu tiên chứa số nguyên K, 0 <= K <= 10000, số tiền mà A có.
- Dòng thứ 2 chứa số nguyên N, 2 <= N <= 100, số thành phố.
- Dòng thứ 3 chứa số nguyên R, 1 <= R <= 10000, tổng số ñoạn ñường.
- Mỗi dòng trong số R dòng tiếp theo mô tả một ñoạn ñường bằng các số S,
D, L và T cách nhau bởi ít nhất một khoảng trắng.
+ S là thành phố khởi hành, 1 <= S <= N.
+ D là thành phố ñến, 1 <= D <= N.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 96
+ L là ñộ dài của ñoạn ñường, 1 <= L <= 100.
+ T là lộ phí, 0 <= T <= 100.
Chú ý rằng giữa 2 thành phố có thể có nhiều ñoạn ñường nối 2 thành phố này.
Dữ liệu ra: ROADS.OUT
Chỉ có duy nhất 1 dòng chứa tổng ñộ dài của ñường ñi ngắn nhất từ 1->N và nhỏ
hơn K.
ROADS.IN
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
ROADS.OUT
11
ROADS.IN
0
4
4
1 4 5 2
1 2 1 0
2 3 1 1
3 4 1 0
ROADS.OUT
-1
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 97
Bài 12: Bài toán luồng cực ñại trong mạng Mục tiêu
- Trình bày ñược tư tưởng chủ ñạo của thuật toán Ford_Fulkerson và cài ñặt ñược
thuật toán.
- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.
- Sinh viên có khả năng tự học.
a. Nhắc lại lý thuyết
ðịnh nghĩa 1. Ta gọi mạng là ñồ thị có hướng G = (V,E), trong ñó có duy
nhất một ñỉnh s không có cung ñi vào gọi là ñiểm phát, duy nhất một ñỉnh t không
có cung ñi ra gọi là ñiểm thu và mỗi cung e = (v,w) ∈ E ñược gán với một số
không âm c(e) = c(v,w) gọi là khả năng thông qua của cung e.
ðịnh nghĩa 2. Giả sử cho mạng G = (V,E). Ta gọi luồng f trong mạng G =
(V,E) là ánh xạ f: E� R+ gán cho mỗi cung e =(v,w) ∈ E một số thực không âm
f(e) = f(v,w), gọi là luông trên cung e, thoả mãn các ñiều kiện sau:
1. Luồng trên mỗi cung e ∈ E không vượt quá khả năng thông qua của nó: 0
≤ f (e) ≤ c(e),
2. ðiều kiện cân bằng luồng trên mỗi ñỉnh của mạng : Tổng luồng trên các
cung ñi vào ñỉnh v bằng tổng luồng trên các cung ñi ra khỏi ñỉnh v, nếu v ≠ s,t:
0),()()()()(
=−= ∑∑+Γ∈−Γ∈ vwvw
f wvfvfvDiv
Trong ñó )(v−Γ - tập các ñỉnh của mạng mà từ ñó có cung ñến v, )(v+Γ - tập các
ñỉnh của mạng mà từ v có cung ñến nó:
{ } { }.),(:)(,),(:)( EwvVwvEvwVwv ∈∈=Γ∈∈=Γ +−
3.Giá trị của luồng f là số
.),(),()()()(
∑∑−Γ∈+Γ∈
==twsw
twfwsffval
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 98
Bài toán luồng cực ñại trong mạng Cho mạng G=(V,E). Hãy tìm luồng f* trong
mạng với giá trị luồng val(f*) là lớn nhất . Luồng như vậy ta sẽ gọi là luồng cực ñại
trong mạng.
Giải quyết bài toán
Từ mạng G = (V,E) khả năng thông qua các cung và các ñỉnh. Ta sẽ giải
quyết theo hai bước sau:
10 Xác ñịnh mạng G’.
20 Tìm luồng cực ñại trong mạng G’. Bắt ñầu từ luồng zero với khả năng
thông qua cung.
Thuật toán Ford – Fulkerson
1. Xuất phát từ một luồng chấp nhận ñược f.
2. Tìm một ñường ñi tăng luồng P. Nếu không có thì thuật toán kết thúc. Nếu
có, tiếp bước 3 dưới ñây.
3. Nếu δ(P) = +∞ thuật toán kết thúc.
Thuật toán gán nhãn (The labeling algorithm)
1. Nếu t ∈ VT hoặc VT = ∅, thuật toán kết thúc. Ngược lại thì chọn một ñỉnh u
∈ VT ñể thăm và ñưa nó ra khỏi VT. Xét tất cả các ñỉnh cạnh u, tức là xét mọi
cung có dạng (u,v) và (v,u).
2. Nếu (u,v) ∈ E, F(u,v) < C(u,v) và v chưa gán nhãn thì gán nhãn nó và ñưa v
vào tập VT.
3. Nếu (v,u) ∈ E, F(v,u) > 0 và v chưa gán nhãn thì gán nhãn nó và ñưa vào tập
VT.
b. ðề bài tập
Bài 1 Áp dụng thuật toán Ford-Fullkerson tìm luồng cực ñại bằng cách gán nhãn
cho luồng zero sau:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 99
c. Hướng dẫn giải
Bài 1
+ Bước lặp 1: s → a → b → t, δ1 = 1
+ Bước lặp 2: s → a → b → c → e → t, δ2 = 2
7,0
4,0
12,0 3,0
4,0 5,0
9,0
5,0 7,0
4,0
6,0
c
d e
t
b
s
a
c(s+,4)
7,0
4,0
12,0 3,0
4,0 5,0
9,0
5,0 7,0
4,0
6,0
d(s+,7) e(d+,4)
t(e+,2)
b(a+,6)
s
(s,∞)
a(s+,6)
7,4
4,4
12,0 3,0
4,0 5,0
9,0
5,0 7,0
4,0
6,4
c
d e
t
b
s
a
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 100
+ Bước lặp 3: s → c → e → t, δ3 = 1
+ Bước lặp 4: s → d → e → t, δ4 = 7
c(b+,2)
7,4
4,4
12,0 3,0
4,0 5,0
9,0
5,0 7,0
4,0
6,4
d(s+,7) e(c+,2)
t(e+,2)
b(a+,2)
s
(s,∞)
a(s+,2)
c
7,6
4,4
12,3 3,3
4,2 5,0
9,0
5,0 7,0
4,1
6,6
d e
t
b
s
a
c
7,6
4,4
12,2 3,2
4,2 5,0
9,0
5,0 7,0
4,0
6,6
d e
t
b
s
a
c(s+,4)
7,6
4,4
12,2 3,2
4,2 5,0
9,0
5,0 7,0
4,0
6,6
d(s+,7) e(c+,1)
t(e+,1)
b(a+,1)
s
(s,∞)
a(s+,0)
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 101
+ Bước lặp 5: s → c → d → e → t, δ5 = 2
+ Bước lặp 6: Không còn ñường tăng luồng nữa, Val(fmax) = 6+3+7 = 16.
d. Bài tập tự giải
Bài tập 1 : Cho G=(V,E) ñồ thị có hướng trong ñó không có cung (s,t). Chứng
minh rằng số ñường ñi cơ bản nối hai ñỉnh s và t là bằng số ít nhất các ñỉnh của ñồ
thị cần loại bỏ ñể trong ñồ thị không còn ñường ñi nối s với t.
c(s+,3)
7,6
4,4
12,3 3,3
4,2 5,0
9,0
5,0 7,0
4,1
6,6
d(s+,7) e(d+,7)
t(e+,7)
b(a+,1)
s
(s,∞)
a(s+,0)
c
7,6
4,4
12,10 3,3
4,2 5,0
9,7
5,0 7,7
4,1
6,6
d e
t
b
s
a
c(s+,3)
7,6
4,4
12,10 3,3
4,2 5,0
9,7
5,0 7,7
4,1
6,6
d(c+,3) e(d+,2)
t(e+,2)
b(a+,1)
s
(s,∞)
a(s+,0)
c
7,6
4,4
12,12 3,3
4,2 5,0
9,9
5,2 7,7
4,3
6,6
d e
t
b
s
a
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 102
Bài tập 2 : Xây dựng thuật toán tìm tập E1 tất cả các cung của ñồ thị mà việc tăng
khả năng thông qua của bất kỳ cung nào trong E ñều dẫn ñến tăng giá trị của luồng
cực ñại trong mạng.
Bài tập 3 : Cho hai dãy số nguyên dương {pi, i=1,2,…,m} và {qj, j=1,2,…,n}. Hãy
xây dựng ma trận A={aij : i=1,2,…,m; j=1,2,…n} với các phần tử
ai j ∈ {0,1} có tổng các phần tử trên dòng i là pi , tổng các phần tử trên cột j là qj.
Bài tập 4 : Có m chàng trai, n cô gái và k bà mối, mỗi bà mối p (p=1,2,…,k) có một
danh sách Lp một số chàng trai và cô gái trong số các chàng trai và cô gái nói trên là
khách hàng của bà ta. Bà mối p có thể se duyên cho bất cứ cặp trai gái nào là khách
hàng của bà ta, nhưng không ñủ sức tổ chức quá dp ñám cưới. Hãy xây dựng thuật
toán căn cứ vào danh sách Lp, dp, p=1,2,…,k; ñưa ra cách tổ chức nhiều nhất các
ñám cưới giữa m chàng trai và n cô gái với sự giúp ñỡ của các bà mối.
Bài tập 5 : Chuyển bi
Cậu bé vẽ N (N<=100) vòng tròn, ñánh số từ 1 tới N và tô màu các vòng tròn
ñó (có thể có các vòng tròn có màu giống nhau), sau ñó nối từng cặp các cung ñịnh
hướng, mỗi cung có một màu nhất ñịnh. Các màu (của cung và vòng tròn) ñược
ñánh số từ 1 ñến 100.
Cậu bé chọn 3 số nguyên khác nhau L, K và Q nằm trong phạm vi từ 1 tới N,
ñặt vào trong các vòng tròn số L và K mỗi vòng một hòn bi, sau ñó bắt ñầu di
chuyển bi theo nguyên tắc sau:
- Bi chỉ ñược chuyển theo cung có màu trùng với màu của vòng tròn chứa
viên bi thứ 2.
- Bi chỉ ñược chuyển theo chiều cung
- Hai viên bi không ñược ñồng thời ở cùng một vòng tròn;
- Không nhất thiết phải di chuyển lần lượt các viên bi,
- Quá trình di chuyển kết thúc, khi một trong hai viên bi tới vòng tròn Q.
Hãy lập trình xác ñịnh cách di chuyển ñể chấm dứt quá trình sau một số ít
nhất các bước chuyển.
Dữ liệu vào từ file BL.INP:
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 103
- Dòng ñầu: 4 số nguyên N L K Q
- Dòng thứ 2: N số nguyên C1, C2,…,Cn; Ci là màu vòng tròn i
- Dòng thứ 3: số nguyên M (0 < M < 10000)
- M dòng sau: mỗi dòng 3 số nguyên Ai Bi Di; xác ñịnh cung màu Di
từ vòng tròn Ai tới vòng tròn Bi.
Các số trên một dòng cách nhau một dấu cách.
Kết quả ñưa ra file BL.OUT:
- Dòng ñầu: CO hoặc KHONG, cho biết quá trình có kết thúc ñược
hay không,
- Nếu dòng ñầu là CO thì dòng 2 chứa số nguyên xác ñịnh số bước
chuyển tối thiểu .
BL.INP BL.OUT
5 3 4 1
2 3 2 1 4
8
2 1 2
4 1 5
4 5 2
4 5 2
5 1 3
3 2 2
2 3 4
5 3 1
3 5 1
CO
3
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 104
Bài tập 6 : Bảng ñiện
Một lưới ô vuông ñược phủ trên một bảng ñiện hình vuông. Vị trí nằm trên
giao của 2 ñường kề của lưới sẽ ñược gọi là nút. Tất cả có nxn nút trên lưới.
Có một số nút chứa tiếp ñiểm. Nhiệm vụ của bạn là cần nối các tiếp ñiểm với
các nút ở trên biên của bảng bởi các ñoạn dây dẫn (gọi là các mạch). Các mạch chỉ
ñược chạy dọc theo các ñường kẻ của lưới (nghĩa là không ñược chạy theo ñường
chéo). Hai mạch không ñược phép có ñiểm chung, vì vậy hai mạch bất kỳ không
ñược phép cùng chạy qua cùng một ñoạn ñường kẻ của lưới cũng như không ñược
chạy qua cùng một nút của lưới. Các mạch cũng không ñược chạy dọc theo các
ñoạn kẻ của lưới ở trên biên (mạch phải kết thúc khi nó gặp biên) và cũng không
ñược chạy qua nút chứa tiếp ñiểm khác.
Ví dụ: Bảng ñiện và các tiếp ñiểm ñược cho trong hình 2a. Nút tô ñậm trong
hình vẽ thể hiện vị trí các tiếp ñiểm.
Yêu cầu: Viết chương trình cho phép nối ñược một số nhiều nhất các tiếp
ñiểm với biên. Các tiếp ñiểm ở trên biên ñã thỏa mãn ñòi hỏi ñặt ra, vì thế không
nhất thiết phải thực hiện mạch nối chúng. Nếu như có nhiều lời giải thì chi cần ñưa
ra một trong số chúng.
Dữ liệu vào: file văn bản ELE.INP:
- Dòng ñầu tiên chứa số nguyên n (3 <= n <= 15).
- Mỗi dòng trong số n dòng tiếp theo chứa n ký tự phân cách nhau bởi
một dấu cách. Mỗi ký tự chỉ là 0 hoặc 1. Ký tự 1 thể hiện tiếp ñiểm,
ký tự 0 thể hiện nút không có tiếp ñiểm trên vị trí tương ứng của lưới.
Các nút ñược ñánh số từ 1 ñến n*n theo thứ tự từ trái sang phải, từ
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 105
trên xuống dưới. Chỉ số của nút chứa tiếp ñiểm sẽ là chỉ số của tiếp
ñiểm.
Kết quả: ghi ra file ELE.OUT:
- Dòng ñầu tiên chứa k là số tiếp ñiểm lớn nhất có thể nối với biên bởi
các mạch.
- Mỗi dòng trong số k dòng tiếp theo mô tả một mạch nối một trong
số k tiếp ñiểm với biên theo qui cách sau: ñầu tiên là chỉ số của tiếp
ñiểm ñược nối, tiếp ñến là dãy các ký tự mô tả hướng của mạch nối:
E: ñông, W: tây, N: bắc, S: nam. Giữa chỉ số và dãy ký tự phải có
ñúng một dấu cách, còn giữa các ký tự trong dãy ký tự không ñược có
dấu cách.
Kết quả phải ñược ñưa ra theo thứ tự tăng dần của chỉ số tiếp ñiểm.
Ví dụ:
ELE.IN ELE.OUT
6
0 0 0 1 1 1
0 0 0 0 1 0
0 0 0 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 0 0 1 0 1
11 E
16 NWN
17 SE
27 S
28 NWWSS
29 S
Bài tập 7: Một khóa học gồm N môn học, môn học i phải học trong ti ngày. Giữa
các môn học có mối quan hệ trước/sau: có môn học chỉ học ñược sau khi ñã học
một số môn học khác. Mối quan hệ ñó ñược thể hiện bởi một mảng hai chiều A[i, j];
i, j = 1, …, N trong ñó A[i, j] = 1/0 và A[i, i] bằng 0 với mọi i, A[i, j] = 1 khi và chỉ
khi môn học i phải ñược dạy xong trước khi học môn j (ngày kết thúc môn i phải
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 106
trứơc ngày bắt ñầu môn j). Môn học i phải dạy trước môn học j nếu có một dãy môn
học i1, i2, …, ik sao cho a[it, it+1] = 1, 1 <= t <= k-1, i1=i và ik=j. Nếu có một nhóm
các môn học từng ñôi một không có quan hệ trước/sau thì trong mỗi ngày, về
nguyên tắc, ta có thể học ñồng thời tất cả những môn học này (nếu không vi phạm
quan hệ với các môn học khác). Mảng A[i, j] ñược gọi là bế tắc nếu có một dãy các
môn học i1, i2,…, ik, k > 1, mà môn i1 phải dạy trước môn i2, môn i2 phải dạy trước
môn i3, …, môn ik-1 phải dạy trước môn ik, môn ik phải dạy trước môn i1.
Hãy viết chương trình làm các việc sau:
1. Hãy xét xem mảng A có bế tắc hay không.
2. Nếu mảng A không bế tắc, hãy tính xem khóa học có thể kết thúc trong
thời gian nhanh nhất là bao nhiêu ngày.
3. Theo các học bảo ñảm thời gian hoàn thành ngắn nhất ở câu 2, hãy tính
xem một học sinh trong quá trình học phải học ñồng thời trong một ngày
nhiều nhất bao nhiêu môn.
Dữ liệu vào ñược cho bởi file text có tên MH.DAT trong ñó số N ghi ở dòng
thứ nhất, trong nhóm N dòng tiếp theo, dòng thứ i ghi N số A[i, 1], …, A[i, N] dòng
cuối cùng ghi N số nguyên dượng ti không lớn hơn 30, 1 <= i <= N; N <= 30.
Kết quả ghi ra file TKB.DAT như sau: dòng thứ nhất ghi số 1/0 tùy theo
mảng A bế tắc / không bế tắc. Nếu dòng thứ nhất ghi số 0, ta mới ghi tiếp kết quả
câu 2 và 3.
Kết quả câu 2 ghi tiếp vào file TKB.DAT N+1 dòng như sau: dòng dầu ghi
số T là số ngày tối thiểu có thể hoàn thành khóa học, tiếp theo là N dòng trong ñó
dòng thứ i ghi 2 số X, Y với ý nghĩa môn học thứ i học từ ngày thứ X ñến ngày thứ
Y (chú ý rằng Y – X = ti – 1).
Kết quả câu 3 ghi tiếp vào file TKB.DAT như sau: dòng thứ nhất ghi 2 số Z,
W với ý nghĩa trong ngày Z phải học W môn (W là số nhiều nhất các môn học phải
học ñồng thời trong một ngày), tiếp theo là một dòng ghi tên các môn học phải học
ñồng thời trong ngày Z.
Trong các câu 2 và 3, có thể có nhiều lời giải tương ñương chỉ cần ñưa ra một lời
giải.
Ví dụ 1
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 107
MH.DAT TKB.DAT
4
0 1 0 0
0 0 1 0
0 0 0 1
1 0 0 0
1 1 1 1
1
Ví dụ 2
MH.DAT TKB.DAT
7
0 1 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 1
0 0 0 0 0 0 0
2 2 8 4 10 2 3
0
22
1 2
3 4
1 8
12
13 22
13 14
15 17
1 2
1 3
Bài tập 8: Giám ñốc một công ty quyết ñịnh tổ chức buổi tiệc trà gặp gỡ toàn thể
nhân viên trong công ty. Công ty ñựơc tổ chức theo mô hình phân cấp lãnh ñạo và
mối quan hệ thủ trưởng – nhân viên tạo thành cây có gốc là giám ñốc. ðể ñảm bảo
không khí tự nhiên, giám ñốc quyết ñịnh không ñể thủ trưởng và nhân viên dưới
quyền ngồi cùng một bàn. P gọi là thủ trưởng của Q, nếu P là thủ trưởng trực tiếp
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 108
của Q hoặc tồn tại dãy P1, P2, …, Pk (1 < k), sao cho P = P1, Q = Pk và Pi là thủ
trưởng trực tiếp của Pi+1 (i = 1, 2, … , k -1). Tất cả mọi người trong công ty ñược
ñánh số từ 1 ñến N (N là tổng số người trong công ty với giám ñốc bắt ñầu từ 1).
+ Yêu cầu: tính số lượng bàn ít nhất cần thiết ñể có thể bố trí cho mọi người ngồi
theo yêu cầu nêu trên và cho một phương án bố trí người ở mỗi bàn.
+ Dữ liệu vào: file text COMPANY.INP, dòng ñầu tiên là số nguyên m – số ghế tối
ña cho một bàn, dòng thứ 2 – số nguyên N – số người trong công ty, dòng thứ ba
(và các dòng sau nếu cần) là dãy số nguyên, các số cách nhau ít nhất một dấu cách
hoặc nhóm ký tự xuống dòng, số nguyên thứ i trong dãy cho biết ai là thủ trưởng
trực tiếp của nhân viên i. Giám ñốc không có thủ trưởng nên số này bằng 0. 2 <= m
<= 10, 1 <= N <= 200.
+ Kết quả: ñưa ra file text COMPANY.OUT, dòng ñầu tiên là số bàn ít nhất cần
thiết, các dòng sau mỗi dòng tương ứng với một bàn và chứa dãy số nguyên xác
ñịnh ai ñược bố trí ngồi sau bàn ñó.
Ví dụ:
COMPANY.INP
4
13
0 1 9 9 9 2 2 1 1 7 8 8 10
File kết quả COMPANY.OUT có thể có nội dung:
5
13 3 4 5
10 6 8
7 9 11 12
2
1
Bài tập 9: Trên bàn cờ NxN, hãy tìm cách sắp xếp số lượng tối ña các con hậu sao
cho không con nào có thể ăn con nào.
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 109
Bài tập 10: Cho 1 ñồ thị có hướng G, hãy tìm một tập hợp X0 ít nhất các ñỉnh của G
sao cho mọi ñỉnh i của G hoặc thuộc X0 hoặc i nối trực tiếp với ñịnh j thuộc X0.
Bài tập 11: Trên bàn cờ NxN, hãy tìm cách sắp xếp số lượng tối thiểu các con hậu
sao cho mọi ô cờ trên bàn cờ bị chiếu bởi ít nhất 1 con.
Bài tập 12: Một ký túc xá có 15 cô gái. Hàng ngày các cô ñi chơi với nhau theo bộ
3. Hỏi có thể ñưa các cô ñi chơi trong tối ña bao nhiêu ngày ñể không có 2 cô nào ñi
chung trong một bộ 3 quá 1 lần.
Hãy tổng quát hóa bài toán.
Bài tập 13: Một số hải cảng x1, x2, x3… có các mặt hàng mà các hải cảng y1, y2,
y3…cần ñến. Lượng hàng có ở xi là si và yêu cầu hàng hóa của yi là di. Nếu có tàu ñi
từ xi tới yj thì ta ký hiệu cij là tổng lượng hàng mà các tàu có thể vận chuyển từ xi tới
yj. Vậy có thể thỏa mãn mọi yêu cầu không? Tổ chức vận chuyển ra sao? Hãy viết
chương trình giải quyết bài toán trên.
Bài tập 14: Trong một cuộc du lịch, m gia ñình phân nhau ñi trên n xe. Các gia ñình
tương ứng có r1, r2, …, rm người và các xe tương ứng có s1, s2, …, sn chỗ ngồi. Hãy
tìm cách phân phối sao cho 2 người cùng gia ñình không ngồi chung một xe hoặc
cho biết không thể làm như vậy.
Bài tập15: Trong một trường trung học, mỗi học sinh nữ có m bạn nam và mỗi học
sinh nam có m bạn nữ. Hãy chỉ ra cách sắp xếp ñể mỗi cô gái có thể lần lượt khiêu
vũ với các bạn trai của mình và các chàng trai có thể lần lượt khiêu vũ với các bạn
gái của mình.
Bài 16: Một nhà in phải sản xuất n cuốn sách bằng 2 máy: một ñể in, một ñể ñóng
sách. Gọi ak là thời gian cần cho việc in cuốn thứ k và bk là thời gian cần cho việc
ñóng cuốn ñó. Tất nhiên là sách phải in xong mới ñóng, do ñó máy ñóng có thể phải
chờ ñợi lâu hay chóng. Vậy tiến hành theo thứ tự nào ñể có thể xong việc sớm nhất.
Bài tập 17: Ổn ñịnh
Trong một lớp có N dãy bàn và mỗi dãy có M chỗ ngồi. Trong lớp có K cán
sự lớp. Mỗi một cán sự cầm một ñề bài tập. Các cán sự này có nhiệm vụ chuyển ñề
bài tập ñến các học sinh khác ngồi kề mình ở phía trước, sau, trái và phải. Sau khi
các cán sự làm xong công việc của mình, mỗi học sinh thông báo số lượng ñề bài
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
Trang 110
tập mình ñã nhận ñược. Dựa trên thông tin này hãy xác ñịnh vị trí của các cán sự
trong lớp.
Bài tập 18: Có một máy thu và một máy phát tín hiệu. Giả sử máy phát có thể phát
ñi 5 loại tín hiệu khác nhau a, b, c, d, e. Ở máy thu mỗi tín hiệu có thể ñược hiểu
theo 2 cách khác nhau: tín hiệu a có thể hiểu p hay q, tín hiệu b có thể hiểu q hay r,
... Số cực ñại các tín hiệu mà ta có thể sử dụng là bao nhiêu ñể cho ở máy thu không
xảy ra nhầm lẫn giữa các tín hiệu ñược sử dụng.