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
HỌC PHẦN TOÁN RỜI RẠC 2
ðại học
Trình ñộ ñào tạo
:
Chính quy/Liên thông
:
Hệ ñào tạo
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
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
Trang 2
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
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
Trang 3
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
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
Trang 5
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
c. ðồ thị G, G1, G2, G3, G4 và G5 có chu trình ko? Chỉ ra các chu trình của ñồ thị
5
2
1
8
00
G4
3
6
4
7
9
G2
G3
G1
(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ị
1,2,3,4 (1,2);(1,4);(2,3);(2,4);(3,4) Vô hướng G1
5,6,7 (5,6);(5,7);(6,7) Có hướng G2
8,9 Vô hướng (8,9) G3
0 G4
(1,2);(1,4);(2,3);(2,4);(3,4); 1,2,3,4,5,6,7,8,9,0 Hỗn hợp G
(8,9)
(5,6);(5,7);(6,7)
b.
Tên ñồ thị Tính liên thông Tên thành phần liên thông
Có G1 G1
Trang 6
Có G2 G2
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
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 (1,2,4,1);(1,2,3,4,1);(2,3,4,2) Có
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
) hòn ñảo và hai hòn ñảo bất kì thuộc quần ñảo ñều Bài 1. Một quần ñảo có n( n
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.
Trang 7
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
ðể 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.
nối với 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
, mà bạn tương nhau. Khi ñó thông qua các bạn tương ứng với các ñỉnh thuộc xích
ứ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
là một trong liên thông nên có ít nhất một xich nối giữa hai ñỉnh này. Giả sử
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:
Trang 8
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
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
Trang 9
có)?
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
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
5
2
1
8
00
G4
3
6
4
7
9
G2
G3
G1
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
Trang 10
Bài 1
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
b. danh sách Tên ñồ thị a. ma trận kề c.danh sách kề
cạnh(cung)
Danh sách cạnh G1 1 2 3 4 1 2 4
1 2 0 1 0 1 1 2 1 4
1 4 1 0 0 1 2 3 4
2 3 0 0 0 1 3 4 1 2 3
2 4 1 1 1 0 4
3 4
5 6 7 G2 Danh sách cung 5 6 7
0 0 1 5 5 6 6 7
1 0 1 6 5 7
0 0 0 7 6 7
Danh sách cạnh 8 9 8 9 G3
8 9 9 8 0 1 8
1 0 9
0 G4
0 0
G 1 2 3 4 5 6 7 8 9 0 Danh sách cung 1 2 4
1 0 1 0 1 0 0 0 0 0 0 1 2 2 1 4
2 1 0 0 1 0 0 0 0 0 0 1 4 3 4
3 0 0 0 1 0 0 0 0 0 0 2 1 4 1 2 3
4 1 1 1 0 0 0 0 0 0 0 2 3 5 6 7
Trang 11
5 0 0 0 0 0 0 1 0 0 0 2 4 6 7
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
3 2 0 0 0 0 1 0 1 0 0 0 6 8 9
3 4 0 0 0 0 0 0 0 0 0 0 7 9 8
4 1 0 0 0 0 0 0 0 0 1 0 8 0
4 2 0 0 0 0 0 0 0 1 0 0 9
4 3 0 0 0 0 0 0 0 0 0 0 0
5 6
5 7
6 7
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;
Trang 12
node=record
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
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,’:’);
Trang 13
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
while t^.next<>nil do
begin
write(t^.v:4);
t:=t^.next;
end;
end;
readln;
End.
Trang 14
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
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.ư.
Trang 15
ñườ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
ðị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?
Trang 16
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
c
b
a
d
e
G1
ðồ 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ẻ
b
a
c
d
G2
ðồ 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
Trang 17
lẻ
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
a
b
e
d
c
f
g
G3
ðồ 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ẻ
1
5
2
4
3
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ẻ
Trang 18
Bài 2
Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010
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).
Trang 19
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
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 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 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? Trang 20 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 ðồ thị G1 là ñồ thị Hamilton ðồ thị G2 là ñồ thị nửa Hamilton Trang 21 ðồ thị G3 không có chu trình hay ñường ñi Hamilton Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 G4 ðồ thị G4 là ñồ thị Hamilton, vì có chu trình Hamilton (1,3,5,2,4,1) Trang 22 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 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á Trang 23 ñế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 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} ; Trang 24 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 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; Trang 25 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 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); Trang 26 End; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 27 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 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 Trang 28 (*ð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 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); Trang 29 BEGIN Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 *) Trang 30 begin Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 31 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 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 Trang 32 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 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 ñồ Trang 34 thị sau: Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 : Trang 35 3 5 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 So tph cua do thi la:3 0 1 1 1 0 0 0 0 0 TPLT 1 bao gom cac dinh: 1 2 3 4 1 0 1 0 0 0 0 0 0 TPLT 2 bao gom cac dinh: 5 8 1 1 0 1 0 0 0 0 0 TPLT 3 bao gom cac dinh: 6 7 9 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 Trang 36 0 0 0 0 0 0 1 0 1 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. Trang 37 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 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; Trang 38 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 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; Trang 39 (*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 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: Trang 40 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 3 0 1 1 2 3 4 4 0 2 2 1 3 3 0 1 3 2 4 0 0 8 4 1 3 9 0 7 5 8 9 0 6 6 7 9 0 0 5 7 6 9 7 0 6 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 Trang 41 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 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ố. Trang 42 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 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; Trang 43 End; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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; Trang 44 Timduong; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. Trang 45 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 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; Trang 46 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 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 Trang 47 qf: = 0 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 *) Trang 48 Procedure DuyetCR; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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; Trang 49 REPEAT Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 50 Docfile; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. Trang 51 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 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 Trang 52 trình. Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 53 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 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: Vt Bước E Et {1} Khởi tạo {} {1,5} 1 {(1,5)} { (1,5); (5,4); } {1,5,4} 2 { (1,5); (5,4);(4,2) } {1,5,4,2} 3 { (1,5); (5,4);(4,2) và {1,5,4,2,3}=V => dừng 4 (4,3) } 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à Trang 54 (1,5) Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 - 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. Trang 55 Á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 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 Trang 56 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 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 Trang 57 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 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 Trang 58 1 8 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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} Trang 59 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 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} } Trang 60 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 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] Trang 61 ð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 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; Trang 62 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 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 Trang 63 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 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 (*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 Trang 64 (* 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 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; Trang 65 Exit; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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; Trang 66 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 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} Trang 67 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 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 Trang 68 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 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*) Trang 69 inc(solT); Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 T [solT,1]: = i; T [solT,2]: = j; UNILT U = X; End; BEGIN Docfile; Timcay; Ghifile; END. Trang 70 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 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: Trang 71 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 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 Trang 72 ñế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 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ó: Trang 73 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 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 D[1],T[1] D[2],T[2] D[3],T[3] D[4],T[4] ðỉnh 5
ñược Các ñỉnh
chưa xét chọn 4,5 9,5 12,5 1,3,4,2 5 Khởi tạo ∞ 4,5 9,5 12.5 1,3,2 4 1 7,4 4,5 9,5 12,5 1,3 2 2 7,4 4,5 9,5 12,5 1 3 3 7,4 4,5 9,5 12,5 1 4 7,4 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 < ∞. Trang 74 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(cid:1)4(cid:1)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 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 (-). ðỉnh 1 ðỉnh 2 ðỉnh 3 ðỉnh 4 ðỉnh 5 ðỉnh 6 Bước lặp Khởi 0, 1 1, 1* ∞, 1 ∞, 1 ∞, 1 ∞, 1 - - 6, 2 3, 2* ∞, 1 8, 2 1 - - 4, 4* - 7, 4 8, 2 2 - - - 7, 4 5, 3* 3 - - - 6, 6* - 4 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 Trang 75 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 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 (cid:1) Q.TT = 1km; Q.TX (cid:1) Q.HM = 7km; Q.TX (cid:1) 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 (cid:1) Q.HM = ∞; Q.TT (cid:1) Q.TH = 3km; Trang 76 Q.TT (cid:1) 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 Q.TT (cid:1) 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 (cid:1) 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(cid:1) 4 (cid:1) 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 Trang 77 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 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 (cid:1) 2 = 4 Trang 78 1 (cid:1) 3 = ∞ Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 1 (cid:1) 4 = ∞ 1 (cid:1) 5 = ∞ Ta thấy có ñường ñi duy nhất là 1(cid:1)2. Tiếp tục tính khoảng cách từ 2 (cid:1) 3, 4, 5 ta có: 2 (cid:1) 3 = 10 2 (cid:1) 4 = 2 2 (cid:1) 5 = 8 NX: Quãng ñường 2 (cid:1) 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
(cid:1) 3, chỉ còn ñường 4 (cid:1) 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 (cid:1) 5 là 1 (cid:1) 2 (cid:1)4 (cid:1) 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,4* 1 2,12 2,14 2,6* ---- ---- 2 ---- ---- 4,7* ---- ---- 3 ---- ---- ---- ---- ---- 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. Trang 79 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 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 (cid:1) 4 1 2 3 4 5 Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞ Trang 80 ---- 1,3* 1 ---- ---- 1,12 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 2 ---- ---- ---- 2,7* 2,8 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 trongso> (tuỳ vào bài toán 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] ñường ñi mới, ta phải dán lại: Trang 81 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 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 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; Trang 82 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 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; Trang 83 End; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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*) Trang 84 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 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*) Trang 85 End; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 86 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 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: -1 1 2 -1 -1 -1 5 3 1 -1 -1 -1 -1 -1 3 5 2 7 -1 -1 -1 -1 -1 1 4 5 3 7 -1 5 -1 13 -1 -1 -1 5 -1 2 -1 2 6 -1 -1 -1 -1 2 -1 6 -1 -1 -1 13 -1 6 -1 7 Trang 87 Ta tìm ñường ñi bắt ñầu từ ñỉnh 1. Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. ðỉnh có
trọng số Bước Tập A Tập B Mảng trongso Mảng Truoc nhỏ nhất trong B [1] [2,3,4,5,6,7] [0,M,M,M,M,M,M] [-1,0,0,0,0,0,0,] B1 [1] [2,3,4,5,6,7] [0,1,2,5,M,M,M] [-1,1,1,1,0] B2 2 [1,2] [3,4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0] B3 3 [1,2,3] [4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0] B4 4 [1,2,3,4] [5,6,7] [0,1,2,4,8,M,17] [-1,1,1,2,4,0,4] B5 5 [1,2,3,4,5] [6,7] [0,1,2,4,8,10,17] [-1,1,1,2,4,5,4] B6 6 [1,2,3,4,5,6] [0,1,2,4,8,10,16] [-1,1,1,2,4,5,6] [7] B7 7 [1,2,3,4,5,6,7] nt Nt [] B8 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 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. Trang 88 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 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 ; 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. Trang 89 tap:set of Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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*) Trang 90 tapA:= [xp] Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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; Trang 91 UNILT tapB = [ ]; Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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 Trang 92 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 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. Trang 93 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 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à: Chi phí Phương tiện Tốc ñộ
(km/h) (ñ/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á ð Trang 94 ñồng. Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 - 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. Trang 95 + 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 + T là lộ phí, 0 <= T <= 100. + L là ñộ dài của ñoạn ñường, 1 <= L <= 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 ROADS.IN 5 0 6 4 7 4 1 2 2 3 1 4 5 2 2 4 3 3 1 2 1 0 3 4 2 4 2 3 1 1 1 3 4 1 3 4 1 0 4 6 2 1 ROADS.OUT 3 5 2 0 -1 5 4 3 2 ROADS.OUT Trang 96 11 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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(cid:1) 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 Div v
)( = − ) = 0 f ( ( ∑
−Γ∈
w vf
)(
)
v ∑
+Γ∈ wvf
,(
)
v w )(v−Γ )(v+Γ 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: Trong ñó - tập các ñỉnh của mạng mà từ ñó có cung ñến v, - tập các − + Γ v
)( = (: ∈ ∈ E Γ v
)( = ,(: ∈ ) ∈ E {
vwVw
), }
, {
wvVw }. ñỉnh của mạng mà từ v có cung ñến nó: val ( f ) = ) = .), ∑
+Γ∈
w wsf
,(
)(
s ∑
−Γ∈
w twf
(
)(
t Trang 97 3.Giá trị của luồng f là số Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 trong mạng. 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 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. Giải quyết bài toán 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 Ford – Fulkerson 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 Thuật toán gán nhãn (The labeling algorithm) 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. ∈ 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 cho luồng zero sau: Trang 98 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 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 a b 7,0 6,0 5,0 4,0 4,0 4,0 s c t 5,0 3,0 12,0 7,0 9,0 e d + Bước lặp 1: s → a → b → t, δ1 = 1 a(s+,6) b(a+,6) 7,0 6,0 5,0 4,0 4,0 4,0 s c(s+,4) t(e+,2) 5,0 3,0 (s,∞) 12,0 7,0 9,0 e(d+,4) d(s+,7) a b 7,4 6,4 5,0 4,4 4,0 4,0 s c t 5,0 3,0 12,0 7,0 9,0 e d + Bước lặp 2: s → a → b → c → e → t, δ2 = 2 Trang 99 c. Hướng dẫn giải
Bài 1 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 a(s+,2) b(a+,2) 7,4 6,4 5,0 4,4 4,0 4,0 s c(b+,2) t(e+,2) 5,0 3,0 (s,∞) 12,0 7,0 9,0 e(c+,2) d(s+,7) a(s+,0) b(a+,1) 7,6 6,6 5,0 4,4 4,0 s 4,2
c(s+,4) t(e+,1) 5,0 3,2 12,2 (s,∞) 7,0 9,0 e(c+,1) d(s+,7) a b 7,6 5,0 6,6 4,4 4,2 4,0 c t s 5,0 3,2 12,2 7,0 9,0 e d + Bước lặp 3: s → c → e → t, δ3 = 1 a b 7,6 6,6 5,0 4,4 4,2 4,1 s c t 5,0 3,3 12,3 7,0 9,0 e d + Bước lặp 4: s → d → e → t, δ4 = 7 Trang 100 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 b a 7,6 6,6 5,0 4,4 4,2 4,1 s t c 5,0 3,3 12,10 7,7 9,7 e d a(s+,0) b(a+,1) 7,6 6,6 5,0 4,4 4,1 s 4,2
c(s+,3) t(e+,7) 5,0 3,3 12,3 (s,∞) 7,0 9,0 e(d+,7) d(s+,7) + Bước lặp 5: s → c → d → e → t, δ5 = 2 a b 7,6 6,6 5,0 4,4 4,2 4,3 s c t 5,2 3,3 12,12 7,7 9,9 e d a(s+,0) b(a+,1) 7,6 6,6 5,0 4,4 4,1 s 4,2
c(s+,3) t(e+,2) 5,0 3,3 12,10 (s,∞) 7,7 9,7 e(d+,2) d(c+,3) + Bước lặp 6: Không còn ñường tăng luồng nữa, Val(fmax) = 6+3+7 = 16. 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. Trang 101 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 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 cực ñại trong mạng. 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 j=1,2,…n} với các phần : trận A={aij 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 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
tử
i=1,2,…,m; 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. 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: Trang 102 Bài tập 5 : Chuyển bi Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 - 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 CO 5 3 4 1 3 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 Trang 103 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. Bài tập 6 : Bảng ñiện 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. Ví dụ: Bảng ñiện và các tiếp ñiểm ñược cho trong hình 2a. Nút tô ñậm trong - 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ừ Trang 104 Dữ liệu vào: file văn bản ELE.INP: Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. - 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. Kết quả: ghi ra file ELE.OUT: ELE.IN ELE.OUT 6 11 E 0 0 0 1 1 1 16 NWN 0 0 0 0 1 0 17 SE 0 0 0 1 1 1 27 S 0 0 0 0 0 0 28 NWWSS 0 0 1 1 1 1 29 S 0 0 0 1 0 1 Ví dụ: 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 Trang 105 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 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. Trang 106 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 MH.DAT TKB.DAT 4 1 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 MH.DAT TKB.DAT 0 7 22 0 1 0 0 0 0 0 1 2 0 0 0 1 0 0 0 3 4 0 0 0 1 0 0 0 1 8 0 0 0 0 1 1 0 12 13 22 0 0 0 0 0 0 0 13 14 0 0 0 0 0 0 1 15 17 0 0 0 0 0 0 0 1 2 2 2 8 4 10 2 3 1 3 Ví dụ 2 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 Trang 107 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à Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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). theo yêu cầu nêu trên và cho một phương án bố trí người ở mỗi bàn. + 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 (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. + 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 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 ñó. + Kết quả: ñưa ra file text COMPANY.OUT, dòng ñầu tiên là số bàn ít nhất cần 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 Ví dụ: cho không con nào có thể ăn con nào. Trang 108 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 Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. sao cho mọi ô cờ trên bàn cờ bị chiếu bởi ít nhất 1 con. 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 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 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ộ 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. cho biết không thể làm như vậy. 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 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 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 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 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 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 Trang 109 Bài tập 17: Ổn ñịnh Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010 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. ñ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. Trang 110 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átc
b
a
d
e
G1
a
b
d
c
G2
a
b
e
d
c
f
g
G3
1
5
2
4
3