110
TRƯỜNG ðẠI HỌC SƯ PHẠM KỸ THUẬT HƯNG YÊN KHOA CÔNG NGHỆ THÔNG TIN BÀI TẬP HỌC PHẦN TOÁN RỜI RẠC 2 Trình ñộ ñào tạo Hệ ñào tạo : : ðại học Chính quy/Liên thông

Mau-HSGD-07-He thong bai tap TRR2 - …dulieu.tailieuhoctap.vn/books/giao-duc-dai-cuong/toan-roi-rac/file... · c. Hướng dẫn giải ... Bài toán luồng cực ñại trong

  • Upload
    letruc

  • View
    224

  • Download
    6

Embed Size (px)

Citation preview

TRƯỜNG ðẠI HỌC SƯ PHẠM KỸ THUẬT HƯNG YÊN

KHOA CÔNG NGHỆ THÔNG TIN

BÀI TẬP

HỌC PHẦN TOÁN RỜI RẠC 2

Trình ñộ ñào tạo

Hệ ñào tạo

:

:

ðại học

Chính quy/Liên thông

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 2

LỜI NÓI ĐẦU

Có thể nói toán học rời rạc là môn tiên quyết và hiệu quả nhất ñể người học

nâng cao tư duy toán học trong phân tích, thiết kế thuật toán và rèn luyện kỹ năng

lập trình với những thuật toán phức tạp. Không những thế nó còn là “cửa ngõ” ñể

người học có thể tiếp cận với rất nhiều modul trong khoa học máy tính (như

Chương trình dịch, lý thuyết tính toán, Trí tuệ nhân tạo,...). Bài tập ñể củng cố

và nâng cao kiến thức trong môn học này

Về nội dung, bám sát với chương trình của nhà trường và hệ thống bài tập

cũng ñược biên soạn theo các chương lý thuyết. Với mỗi chương sẽ ñược chia thành

4 phần:

Phần A. Nhắc lại lý thuyết: tóm tắt các kiến thức cơ bản, các ví dụ và các

lưu ý hữu ích, các kinh nghiệm trong khi lập trình

Phần B. ðề bài tập: ñưa ra các loại bài tập khác nhau, với các mức ñộ khác

nhau.

Phần C. Bài tập mẫu: Hướng dẫn giải một số bài tiêu biểu trong phần B, có

phân tích thuật toán và cài ñặt chương trình.

Phần D. Bài tập tự giải: Người học thực hiện việc giải các bài tập này

Mong rằng tài liệu này ñáp ứng ñược phần nào nhu cầu của học sinh, sinh viên. ðây

là bản ñầu tiên chắc chắn còn rất nhiều sai sót. Nhóm tác giả mong nhận ñược sự

ñóng góp của các thầy cô giáo, các bạn sinh viên và của tất cả những ai quan tâm tới

lĩnh vực này.

Hưng Yên, tháng 7 năm 2010

Bộ môn Công nghệ phần mềm

Khoa Công nghệ thông tin

Trường ñại học sư phạm kỹ thuật Hưng Yên

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 3

MỤC LỤC Bài 1: Các khái niệm cơ bản của Lý thuyết ñồ thị ............................................................5

Mục tiêu ...................................................................................................................5 a. Nhắc lại lý thuyết ..................................................................................................5 b. ðề bài tập..............................................................................................................5 c. Hướng dẫn giải......................................................................................................6 d. Bài tập tự giải .......................................................................................................7

Bài 2: Biểu diễn ñồ thị trên máy tính..............................................................................10 Mục tiêu .................................................................................................................10 a. Nhắc lại lý thuyết ................................................................................................10 b. ðề bài tập............................................................................................................10 c. Hướng dẫn giải....................................................................................................10 d. Bài tập tự giải .....................................................................................................14

Bài 3: ðồ thị Euler .........................................................................................................15 Mục tiêu .................................................................................................................15 a. Nhắc lại lý thuyết ................................................................................................15 b. ðề bài tập............................................................................................................16 c. Hướng dẫn giải....................................................................................................16 d. Bài tập tự giải .....................................................................................................19

Bài 4: ðồ thị hamilton....................................................................................................20 Mục tiêu .................................................................................................................20 a. Nhắc lại lý thuyết ................................................................................................20 b. ðề bài tập............................................................................................................20 c. Hướng dẫn giải....................................................................................................20 d. Bài tập tự giải .....................................................................................................22

Bài 5: Thảo luận cài ñặt ñồ thị, các thuật toán liệt kê chu trình Euler và Hamilton. Thảo luận về bài tập lớn.................................................................................................23

Mục tiêu .................................................................................................................23 a. Nhắc lại lý thuyết ................................................................................................23 b. ðề bài tập............................................................................................................23 c. Hướng dẫn giải....................................................................................................23 d. Bài tập tự giải .....................................................................................................31

Bài 6 Thuật toán tìm kiếm trên ñồ thị và ứng dụng.........................................................34 Mục tiêu .................................................................................................................34 a. Nhắc lại lý thuyết ................................................................................................34 b. ðề bài tập............................................................................................................34 c. Hướng dẫn giải....................................................................................................34 d. Bài tập tự giải .....................................................................................................51

Bài 7: Cây và cây khung ................................................................................................52 Mục tiêu .................................................................................................................52 a. Nhắc lại lý thuyết ................................................................................................52 b. ðề bài tập............................................................................................................53 c. Hướng dẫn giải....................................................................................................54 d. Bài tập tự giải .....................................................................................................55

Bài 8: Thảo luận về cài ñặt thuật toán tìm cây khung nhỏ nhất trên ñồ thị ......................58 Mục tiêu .................................................................................................................58

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 4

a. Nhắc lại lý thuyết ................................................................................................58 b. ðề bài tập............................................................................................................58 c. Hướng dẫn giải....................................................................................................58 d. Bài tập tự giải .....................................................................................................70

Bài 9, 10: Bài toán tìm ñường ñi ngắn nhất ....................................................................71 Mục tiêu .................................................................................................................71 a. Nhắc lại lý thuyết ................................................................................................71 b. ðề bài tập............................................................................................................71 c. Hướng dẫn giải....................................................................................................73 d. Bài tập tự giải .....................................................................................................92

Bài 12: Bài toán luồng cực ñại trong mạng.....................................................................97 Mục tiêu .................................................................................................................97 a. Nhắc lại lý thuyết ................................................................................................97 b. ðề bài tập............................................................................................................98 c. Hướng dẫn giải....................................................................................................99 d. Bài tập tự giải ...................................................................................................101

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 5

Bài 1: Các khái niệm cơ bản của Lý thuyết ñồ thị Mục tiêu

- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.

- Cài ñặt ñược chương trình chuyển ñổi giữa các phương pháp.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

- Hai ñỉnh x, y ñược gọi là cặp ñỉnh liên thông , nếu hoặc giữa x và y có ít nhất một

xích nối với nhau, hoặc tồn tại ít nhất một ñường ñi từ y sang x.

- ðồ thị vô hướng G(V,E) ñược gọi là ñồ thị liên thông, nếu mọi cặp ñỉnh của nó

ñều liên thông.

- ðồ thị có hướng G(V,E) ñược gọi là ñồ thị liên thông mạch, nếu mọi cặp ñỉnh của

nó ñều liên thông.

- Biểu diễn dạng hình học: Giả sử có ñồ thị G(V,E).

Biểu diễn ñỉnh: lấy các ñiểm trên mặt phẳng hay trên không gian tương ứng

với các phần tử của tập V và dùng ngay ký hiệu các phần tử này ñẻ ghi trên các

ñiểm tương ứng.

Biểu diễn cạnh: Nếu cạnh a với hai ñỉnh ñầu là x,y thì nó ñược biểu diễn

bằng ñoạn thẳng hay một ñoạn cong nối giữa hai ñiểm x, y và không ñi qua các

ñiểm tương ứng trong không gian.

Biểu diễn cung: nếu cung a có ñỉnh ñầu là x, ñỉnh cuối là y, thì nó ñược biểu

diễn bằng một ñoạn thẳng hoặc ñoạn cong ñược ñịnh hướng ñi từ x sang y và không

qua các ñiểm tương ứng trung gian khác.

Hình nhận ñược gọi là dạng biểu diễn hình học của ñồ thị G(V, E). ðôi khi

người ta cũng gọi dạng biểu diễn hình học là một ñồ thị.

b. ðề bài tập

Bài 1 Cho G ñồ thị gồm 4 phần G1, G2, G3 và G4 như sau:

a. Chỉ ra tập ñỉnh, cạnh(vô hướng,có hướng, khuyên,..) của mỗi ñồ thị ñã cho? Chỉ

loại ñồ thị ñó?

b. ðồ thị G, G1, G2, G3, G4 và G5 có liên thông ko? Nếu ñồ thị ko liên thông hãy

chỉ ra các thành phần liên thông?

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 6

c. ðồ thị G, G1, G2, G3, G4 và G5 có chu trình ko? Chỉ ra các chu trình của ñồ thị

(nếu có)?

c. Hướng dẫn giải

Bài 1

a.

Tên ñồ thị Tập ñỉnh V Tập cạnh E Loại ñồ thị

G1 1,2,3,4 (1,2);(1,4);(2,3);(2,4);(3,4) Vô hướng

G2 5,6,7 (5,6);(5,7);(6,7) Có hướng

G3 8,9 (8,9) Vô hướng

G4 0

G 1,2,3,4,5,6,7,8,9,0 (1,2);(1,4);(2,3);(2,4);(3,4);

(8,9)

(5,6);(5,7);(6,7)

Hỗn hợp

b.

Tên ñồ thị Tính liên thông Tên thành phần liên thông

G1 Có G1

G2 Có G2

G1

1

4 3

2 5

7 6

8

9

00

G2 G3

G4

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 7

G3 Có G3

G4 Có G4

G Không G1,G2,G3,G4

c.

Tên ñồ thị Có chu trình? Tên chu trình

G1 Có (1,2,4,1);(1,2,3,4,1);(2,3,4,2)

G2 Không

G3 Không

G4 Không

G Có (1,2,4,1);(1,2,3,4,1);(2,3,4,2)

d. Bài tập tự giải

Bài 1. Một quần ñảo có n( n ) hòn ñảo và hai hòn ñảo bất kì thuộc quần ñảo ñều

có số ñầu mối ñường ngầm tới một trong nhưng hòn ñảo nầy ñều nhỏ hơn n. Chứng

minh rằng từ một hòn ñảo tùy ý thuộc quần ñảo ta có thể ñi ñến một hòn ñảo bất kì

khác của quần ñảo bằng ñường ngầm.

Bài 2 Khi về nghỉ hè mỗi bạn học sinh của lớp 11A trường Lê Hồng Phong ñều

trao ñổi ñịa chỉ với ít nhất một nửa số bạn trong lớp. Chứng minh rằng trong thời

gian nghỉ hè mỗi bạn của lớp 11A ñều có thể báo tin trực tiếp hay gián tiếp cho các

bạn trong lớp.

Bài 3 Trong một cuộc họp có ñúng hai ñại biểu không que nhau và mỗi ñại biểu này

có một số lẻ người que ñến dự. Chứng minh rằng luôn luôn có thể xếp một số ñại

bieetr ngồi chen giữa hai ñại biể nói trên , ñể người ngồi giữa hai người mà anh(

chị) ta quen.

Hướng ñẫn:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 8

ðể giải ñược bài toán trên trước hết ta xây dựng các ñồ thị tương ứng, sau ñó vận

dụng kết quả của ñịnh lý 4.1, hệ quả 4.1 và ñịnh lý 4.2 mà suy ra kết luận.

Xuây dựng ñồ thị

• ðỉnh: Lấy các ñiểm trong mặt phẳng hay trong không gian tương ứng với các

hòn ñảo thuộc quần ñảo ( các bạn học sinh trong lớp 11A, các ñại biểu ñến

họp).

• Cạnh: Hai ñiểm x, y ñược nối bằng một cạnh khi và chỉ khi hai hòn ñảo x, y

có ñường ngầm trực tiếp với nhau( các bạn x, y trao ñổi ñịa chỉ cho nhau, các

ñại biểu x, y quen nhau)

- ðồ thị nhân ñược ký hiệu bằng G1 , (G2 , G3)

- ðồ thị G1 mô tả toàn bộ lưới ñường ngầm trong quần ñảo

- ðồ thị G2 mô tả toàn bộ quan hệ trao ñổi ñịa chỉ trong lớp 11A

- ðồ thị G3 mô tả toàn bộ quen biết trong các ñại biểu trong các ñại biểu ñến

dự họp.

Vận dụng kết quả các ñịnh lý ñể suy ra kết luận

- Do hai hòn ñảo bất kì ñều có tổng số ñầu mối ñường ngầm không nhỏ hơn n, nên

hai ñỉnh bất kì của ñồ thị G1 ñều có tổng bậc không nhỏ hơn n. Bởi vậy theo ñịnh lý

4.1. ñồ thị G1 liên thông, nên hai hòn ñảo bất kì có ñường hầm nối với nhau.

- Vì mỗi bạn học sinh trong lớp 11A trao ñổi ñịa chỉ với ít nhất một nửa số bạn tron

lớp, nên bậc của mỗi ñỉnh của G2 không nhỏ hơn một nửa số ñỉnh của ñồ thị. Khi ñó

, theo hệ quả 4.1. ñồ thị G2 liên thông. Bởi vậy hai ñỉnh x, y ñều có xích nối với

nhau. Khi ñó thông qua các bạn tương ứng với các ñỉnh thuộc xích , mà bạn tương

ứng với ñỉnh x báo tin ñược cho tương ứng với ñỉnh y và ngược lại.

- Hai ñại biểu không quen nhau, thì hai ñỉnh tương ứng không kề nhau. Mỗi ñại biểu

này lại có một số lẻ người quen ñến họp, nên trong ñồ thị liên thông G3 có ñúng hai

ñỉnh bậc lẻ và hai ñỉnh này lại không kề nhau. Khi dó, theo ñịnh lý 4.2, hai ñỉnh này

liên thông nên có ít nhất một xich nối giữa hai ñỉnh này. Giả sử là một trong

những mối xích nối giữa hai bậc lẻ này. Dựa vào ta sắp xếp các ñại biểu tương

ứng ngồi giữa hai người mà anh chị quen.

Bài 4 Cho G ñồ thị như sau:

Chỉ ra tập ñỉnh, cạnh(vô hướng,có hướng, khuyên,..) của mỗi ñồ thị ñã cho? Chỉ

loại ñồ thị ñó? ðồ thị có liên thông ko? Nếu ñồ thị ko liên thông hãy chỉ ra các

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 9

thành phần liên thông? ðồ thị có chu trình ko? Chỉ ra các chu trình của ñồ thị (nếu

có)?

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 10

Bài 2: Biểu diễn ñồ thị trên máy tính Mục tiêu

- Nêu ñược các cách biểu diễn ñồ thị và biểu diễn ñồ thị trên máy tính trên máy tính.

- ðưa ra ñược ma trận kề, danh sách các cạnh, cung tương ứng với 1 ñồ thị cho

trước.

- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.

- - Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

b. ðề bài tập

Bài 1 Cho G ñồ thị gồm 4 phần G1, G2, G3 và G4 như sau:

a. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng ma trận kề

b. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng danh sách cạnh(cung)

c. Biểu diễn các ñồ thị G,G1,G2,G3,G4 dưới dạng danh sách kề

Bài 2 Cài ñặt chương trình nhập danh sách kề của ñồ thị từ bàn phím và ñưa danh

sách ñó ra màn hình.

c. Hướng dẫn giải

Bài 1

G1

1

4 3

2 5

7 6

8

9

00

G2 G3

G4

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 11

Tên ñồ thị a. ma trận kề b. danh sách

cạnh(cung)

c.danh sách kề

G1 1 2 3 4

1 0 1 0 1

2 1 0 0 1

3 0 0 0 1

4 1 1 1 0

Danh sách cạnh

1 2

1 4

2 3

2 4

3 4

1 2 4

2 1 4

3 4

4 1 2 3

G2 5 6 7

5 0 0 1

6 1 0 1

7 0 0 0

Danh sách cung

5 6

5 7

6 7

5 6 7

6 7

G3 8 9

8 0 1

9 1 0

Danh sách cạnh

8 9

8 9

9 8

G4 0

0 0

G 1 2 3 4 5 6 7 8 9 0

1 0 1 0 1 0 0 0 0 0 0

2 1 0 0 1 0 0 0 0 0 0

3 0 0 0 1 0 0 0 0 0 0

4 1 1 1 0 0 0 0 0 0 0

5 0 0 0 0 0 0 1 0 0 0

Danh sách cung

1 2

1 4

2 1

2 3

2 4

1 2 4

2 1 4

3 4

4 1 2 3

5 6 7

6 7

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 12

6 0 0 0 0 1 0 1 0 0 0

7 0 0 0 0 0 0 0 0 0 0

8 0 0 0 0 0 0 0 0 1 0

9 0 0 0 0 0 0 0 1 0 0

0 0 0 0 0 0 0 0 0 0 0

3 2

3 4

4 1

4 2

4 3

5 6

5 7

6 7

8 9

9 8

0

Bài 2 Chương trình nhập danh sách kề của ñồ thị từ bàn phím và ñưa danh sách ñó

ra màn hình

Phân tích bài toán :

Trong rất nhiều thuật toán làm việc với ñồ thị chúng ta thường xuyên phải thực hiện

các thao tác: Thêm hoặc bớt một số cạnh. Trong trường hợp này Cấu trúc dữ liệu

dùng ở trên là không thuận tiện. Khi ñó nên chuyển sang sử dụng danh sách kề liên

kết (Linked Adjancency List) như mô tả trong chương trình nhập danh sách kề của

ñồ thị từ bàn phím và ñưa danh sách ñó ra màn hình

Chương trình minh họa :

Program AdjList;

Const

maxV=100;

Type

link=^node;

node=record

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 13

v:integer;

next:link;

End;

Var

j,x,y,m,n,u,v:integer;

t:link;

Ke:array[1. .Vmax] of link;

Begin

Write(‘Cho so canh va dinh cua do thi:’); readln(m,n);

(*Khoi tao*)

for j:=1 to n do Ke[j]:=nil;

for j:=1 to m do

begin

write(‘Cho dinh dau va cuoi cua canh ‘,j,’:’);

readln(x,y);

new(t); t^.v:=x, t^.next:=Ke[y]; Ke[y]:=t;

new(t); t^.v:=y, t^.next:=Ke[x]; Ke[x]:=t;

end;

writeln(‘Danh sach ke cua cac dinh cua do thi:’);

for J:=1 to m do

begin

writeln(‘Danh sachcac dinh ke cua dinh ‘,j,’:’);

t:=Ke[j];

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 14

while t^.next<>nil do

begin

write(t^.v:4);

t:=t^.next;

end;

end;

readln;

End.

d. Bài tập tự giải

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 15

Bài 3: ðồ thị Euler Mục tiêu

- Kiểm tra ñược một ñồ thị bất kỳ có là ñồ thị euler hay không.

- Áp dụng ñược thuật toán tìm chu trình Euler, ñường Euler, với 1 ñồ thị cho trước.

- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau. Cài ñặt

ñược chương trình chuyển ñổi giữa các phương pháp.

- Cài ñặt ñược thuật toán Tìm chu trình Euler.

- Cài ñặt ñược thuật toán duyêt ñồ thị duyệt theo chiều sâu hoặc duyệt theo chiều

rộng.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

- Chu trình (t.ư. ñường ñi) ñơn chứa tất cả các cạnh (hoặc cung) của ñồ thị (vô

hướng hoặc có hướng) G ñược gọi là chu trình (t.ư. ñường ñi) Euler. Một ñồ thị

liên thông (liên thông yếu ñối với ñồ thị có hướng) có chứa một chu trình (t.ư.

ñường ñi) Euler ñược gọi là ñồ thị Euler (t.ư. nửa Euler).

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 16

ðịnh lý

ðồ thị (vô hướng) liên thông G là ñồ thị Euler khi và chỉ khi mọi ñỉnh của G ñều có

bậc chẵn.

Hệ quả

ðồ thị liên thông G là nửa Euler (mà không là Euler) khi và chỉ khi có ñúng hai

ñỉnh bậc lẻ trong G.

Thuật toán vạch ñược một chu trình Euler trong ñồ thị liên thông G có bậc của mọi

ñỉnh là chẵn theo thuật toán Fleury sau ñây.

Xuất phát từ một ñỉnh bất kỳ của G và tuân theo hai quy tắc sau:

1. Mỗi khi ñi qua một cạnh nào thì xoá nó ñi; sau ñó xoá ñỉnh cô lập (nếu có);

2. Không bao giờ ñi qua một cầu, trừ phi không còn cách ñi nào khác.

b. ðề bài tập

Bài 1: ðồ thị sau có là ñồ thị nửa Euler hay ñồ thị Euler ko? Giải thích?

c. Hướng dẫn giải

Bài 1: ðồ thị sau có là ñồ thị nửa Euler hay ñồ thị Euler ko? Giải thích?

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 17

ðồ thị G1 là ñồ thị nửa Euler

Thật vây, các ñỉnh a,b,e có bậc là 2,4,4 là bậc chẵn, các ñỉnh c và d có bậc là 3 là

bậc lẻ

ðồ thị G2 là ñồ thị nửa Euler

Thật vây, các ñỉnh c và d có bậc là 2 là bậc chẵn, các ñỉnh a và c có bậc là 1 là bậc

lẻ

a

b

e

c

d

G1

a

d

b

c

G2

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 18

ðồ thị G3 không là ñồ thị Euler

Thật vậy G3 có 3 ñỉnh a,d và g có bậc là 1 là bậc lẻ

G4

ðồ thị G4 là ñồ thị nửa Euler vì theo hệ quả..

Thật vây, các ñỉnh 3,4,5 có bậc là 2 là bậc chẵn, các ñỉnh 1 và 2 có bậc là 3 là bậc lẻ

Bài 2

g

a

d

b

c

e

f

G3

1

2

3 4

5

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 19

Xuất phát từ u, ta có thể ñi theo cạnh (u,v) hoặc (u,x), giả sử là (u,v) (xoá

(u,v)). Từ v có thể ñi qua một trong các cạnh (v,w), (v,x), (v,t), giả sử (v,w) (xoá

(v,w)). Tiếp tục, có thể ñi theo một trong các cạnh (w,s), (w,y), (w,z), giả sử (w,s)

(xoá (w,s)). ði theo cạnh (s,y) (xoá (s,y) và s). Vì (y,x) là cầu nên có thể ñi theo một

trong hai cạnh (y,w), (y,z), giả sử (y,w) (xoá (y,w)). ði theo (w,z) (xoá (w,z) và w)

và theo (z,y) (xoá (z,y) và z). Tiếp tục ñi theo cạnh (y,x) (xoá (y,x) và y). Vì (x,u) là

cầu nên ñi theo cạnh (x,v) hoặc (x,t), giả sử (x,v) (xoá (x,v)). Tiếp tục ñi theo cạnh

(v,t) (xoá (v,t) và v), theo cạnh (t,x) (xoá cạnh (t,x) và t), cuối cung ñi theo cạnh

(x,u) (xoá (x,u), x và u).

d. Bài tập tự giải

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 20

Bài 4: ðồ thị hamilton Mục tiêu

- Kiểm tra ñược một ñồ thị bất kỳ có là ñồ thị Hamilton hay không.

- Áp dụng ñược thuật toán tìm chu trình Hamilton, ñường Hamilton, với 1 ñồ thị

cho trước.

- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau. Cài ñặt

ñược chương trình chuyển ñổi giữa các phương pháp.

- Cài ñặt ñược thuật toán Tìm chu trình Halmiton.

- Cài ñặt ñược thuật toán duyêt ñồ thị duyệt theo chiều sâu hoặc duyệt theo chiều

rộng.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

- ðồ thị Hamilton(nửa Hamilton) là ñồ thị có chứa một chu trình(ñường ñi)

Hamilton

Hay

ðường ñi (x[1],x[2],…,x[n]) ñược gọi là ñường ñi Hamilton nếu x[i]≠x[j]

(1≤i<j≤n)

Chu trình (x[1],x[2],…,x[n],x[1]) ñược gọi là chu trình Hamilton nếu

x[i]≠x[j] (1≤i<j≤n)

Note! Cho tới nay, vẫn chưa tìm ra phương pháp với ñộ phức tạp ña thức ñể tìm chu

trình cũng như ñường ñi Hamilton trong trướng hợp ñồ thị tổng quát.

Có thể sử dụng thuật toán quay lui ñể liệt kê chu trình Hamilton

b. ðề bài tập

Bài 1: ðồ thị sau có là ñồ thị nửa Hamilton hay ñồ thị Hamilton ko? Giải thích?

c. Hướng dẫn giải

Bài 1: ðồ thị sau có là ñồ thị nửa Hamilton hay ñồ thị Hamilton ko? Giải thích?

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 21

ðồ thị G1 là ñồ thị Hamilton

ðồ thị G2 là ñồ thị nửa Hamilton

ðồ thị G3 không có chu trình hay ñường ñi Hamilton

a

b

e

c

d

G1

a

d

b

c

G2

g

a

d

b

c

e

f

G3

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 22

G4

ðồ thị G4 là ñồ thị Hamilton, vì có chu trình Hamilton (1,3,5,2,4,1)

d. Bài tập tự giải

1

2

3 4

5

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 23

Bài 5: Thảo luận cài ñặt ñồ thị, các thuật toán liệt kê chu trình Euler và Hamilton. Thảo luận về bài tập lớn Mục tiêu

- Lưu trữ ñược ñồ thị trên máy tính theo những phương pháp khác nhau.

- Chuyển ñổi giữa các kiểu biểu diễn ñồ thị trên máy tính.

- Nâng cao khả năng làm việc nhóm.

- Rèn luyện tư duy sáng tạo.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

Xem lại trong bài 3 và bài 4

b. ðề bài tập

Bài 1 Tìm chu trình Euler trong ñồ thị G.

Bài 2 Tìm chu trình Halmiton trong ñồ thị G.

c. Hướng dẫn giải

Bài 1 ðề bài : Cài ñặt chương trình tìm chu trình Euler trong ñồ thị G.

Cho ñồ thị G=(X,E) tồn tại chu trình Euler. Hãy tìm chu trình (chi trình Euler là

chu trình ñi qua tất cả các cạnh của ñồ thị, mỗi cạnh ñi qua ñúng một lần).

Phân tích bài toán :

ðầu vào: ðồ thị G

ðầu ra: Chu trình Euler (nếu có)

2. Thuật toán:

Xuất phát từ một ñỉnh u bất kỳ, khi ñi qua cạnh nào thì xoá cạnh ñó khỏi ñồ thị và

ghi lại từ trái sang phải. Khi thực hiện thuật toán cần lưu ý nếu gặp cạnh bắc cầu

giữa 2 thành phần liên thông thì ta phải xoá hết thành phần liên thông rồi mới xoá

ñến cạnh bắc cầu.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 24

Khi xoá cạnh bắc cầu thì phải loại hết các ñỉnh trơ trọi (nghĩa là không kề với bất cứ

ñỉnh nào thuộc ñồ thị).

Cấu trúc dữ liệu:

Biểu diễn ñồ thị bằng ma trận kề a(i,j), do ñó lưu ý khi xoá ñi một cạnh ta chỉ việc

gán a(i,j)=a(j,i)=0, ñồng thời phải lưu cạnh vừa xoá vào một mảng khác: Mảng Ctr.

Mảng lt: array [1…Nmax] of integer dùng trong thủ tục tìm thành phần liên thông

(giống như một thuật toán tìm thành phần liên thông trình bày ở trên).

Mảng dd: array [1…Nmax] of Boolean, giá trị dd[i] cho biết ñỉnh i bị loại khỏi ñồ

thị hay chưa. Nếu bị lại thì dd[i]=True; ngược lại dd[i]=False;

Thủ tục

Procedure Euler_Cycle;

Begin

STACK:=∅ ; CE:=∅ ;

Chon u la mot dinh nao do cua do thi;

STACK← u;

While STACK<>∅ do

Begin

X:=top(STACK); (* x la phan tu dau STACK)

If Ke(x)<>∅ then

Begin

Y:=dinh dau tien trong danh sach Ke(x);

STACK← y;

(* loai bo canh (x,y) khoi do thi *)

Ke(x):=Ke(x)\ { y} ;

Ke(y):=Ke(y)\{ x} ;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 25

End

Else

Begin

x⇐ STACK; CE⇐ x;

End;

End;

End;

Chương trình minh họa :

Program Chu_trinh_Euler;

Const Nmax=100;

Emax=100;

Var a:array[1…Nmax,1..Nmax]of integer;

Ctr: array[1…Emax,1,2]of integer;

dd: array[1…Nmax]of Boolean;

lt: array[1…Nmax]of integer;

SolC,N:integer;

(*Biến Solc là số cạnh của chu trình, sẽ tăng lên một ñơn vị mỗi khi ta ñi qua

một cạnh*).

Program Timtplt(k:integer);

(* Thủ tục này tìm thành phần liên thông giống như thuật toán tình thành phần

liên thông trình bày ở trên chỉ khác một ñiểm là ta chỉ tìm tplt ñối với các ñỉnh chưa

bị loại khỏi ñồ thị *).

Var i:integer;

Begin lt[k]:=sotp;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 26

For i=1 to N do

If dd[i] and (lt[i]=0) and(a[i,k]=1)then

Begin

lt[i]:=sotp;

Timtplt(i);

End;

End;

Function KTLT (u,v:integer):Boolean;

(* Hàm này kiểm tra xem khi ta xoá cạnh (u,v) ñi thì ñồ thị còn liên thông nữa hay

không? Nếu còn thì số tplt luôn bằng 1. ðây coi như kiểm tra cạnh (u,v) có phải là

cạnh bắc cầu hay không*).

Var i:integer;

Begin(* ðầu tiên ta phải xoá cạnh (u,v) khỏi ñồ thị rồi mới tiến hành kiểm

tra *).

a[u,v]:=0;a[u,v]:=0;

Fillchar(lt,sizeof(lt),0);

(* ðoạn mã sau tìm số tplt của ñồ thị ở ñiểm ñang xét *).

Sotp:=0;

For i=1 to N do

If dd[i] and (lt[i]=0)then

Begin

inc(sotp);

Timtplt(i);

End;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 27

If sotp=1 then KTLT=True

Else

Bengin (*nếu không có cạnh bắc cầu thì khi khôi phục

lại cạnh (u,v)*).

a[u,v]:=1

a[v,u]:=1

KTLT:=False

End;

End;

Procedure Timchutrinh;

Var i,u,dem:integer;

Begin solc:=0;

u:=1;

(* Chu trình của ta xuất phát từ ñỉnh 1, tuy nhiên ñiều này không bắt buộc *)

For i=1 to N do

dd[i] true;

(* Khởi tạo tất cả các giá trị dd[i]=True nghĩa là chưa có ñỉnh nào bị

loại *)

REPEAT

Dem:=0;

(* Biến ñếm là số cạnh kề với ñỉnh u *)

Begin

For i=1 to N do

If a[u,i]=1 then

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 28

Begin (*xoá cạnh (u,i) khỏi ñồ thị *)

a[u,i]:=0

a[i,u]:=0

(*Loại ñỉnh u khỏi ñồ thị*)

dd[u]:=False;

(*ðua cạnh (u,i) vào chu trình*).

inc(solC);

Ctr[solC,1]:=u;

Ctr[solC,2]:=i;

Break;

End;

End

Else

(*Ngược lại nếu còn nhiều cạnh nối với u ta tìm một cạnh không phải là cạnh

bắc cầu và xoá cạnh ñó ñồng thời ñưa nó vào chu trình*)

If dem>1 then

Begin

For i=1 to N do

If (a[u,i]=1 and dd[i] and KTLT(u,i)then

(*Nếu cạnh (u,i) thoả mãn không phải là cạnh bắc cầu thì ta chọn:

Nghĩa là nó phải kề với u, chưa bị loại khỏi ñồ thị và sau khi xoá cạnh kề ñó

thì ñồ thị vẫn liên thông. Riêng ñiều kiện thứ 3 ta dùng hàm KTLT(u,i) ñể

kiểm tra xem khi xáo cạnh (u,i) ñi thì ñồ thị còn liên thông nữa hay không*).

Begin

(*ðoạn mã sau xoá cạnh (u,i) và ñưa cạnh này

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 29

vào chu trình*).

a[u,i]:=0

a[i,u]:=0

inc(solC);

Ctr[solC,1]:=u;

Ctr[solC,2]:=i;

Break;

(*Sau khi tìm ñược ñỉnh i thì ta phải thoát khỏi vòng lặp For nếu không có

lệnh Break thì chương trình sẽ chạy sai*).

End;

End;

(*Chuẩn bị cho phép tiếp chu trình của chúng ta lại xuất phát từ ñỉnh*)

u:=1;

UNTIL dem=0;

End;

Procedure Ghifile;

Var f:text;

I:integer;

Begin

Assign(f,’kq.out’);Rewrite(f);

For i:=1 to solC do

writeln(f,Ctr[i,1],’ ‘,Ctr[i,2]);

Close(f);

BEGIN

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 30

Docfile;

Timchutrinh;

Ghifile;

END.

Bài 2 ðề bài : Liệt kê tất cả các chu trình Hamilton của ñồ thị

Phân tích bài toán :

Thuật toán sau ñây ñược xây dựng dựa trên cơ sở thuật toán quay lui cho phép liệt

kê tất cả các chu trình Hamilton của ñồ thị.

Hình dưới ñây mô tả cây tìm kiếm theo thuật toán vừa mô tả.

ðồ thị và cây liệt kê chu trình Hamilton của nó theo thuật toán quay lui.

Trong trường hợp ñồ thị có không quá nhiều cạnh thuật toán trên có thể sử dụng ñể

kiểm tra ñồ thị có phải là Hamilton hay không.

Chương trình minh họa :

Procedure Hamilton(k);

(* liet ke cac chu trinh Hamilton thu duoc bang viec phat trien day dinh (X[1],. . .

, X[k-1]) cua do thi G=(V,E) cho boi danh sach ke: Ke(v), v∈ V *)

begin

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 31

for y ∈ Ke(X[k-1]) do

if (k =N+1) and (y=v0) then Ghinhan(X[1],. . . , X[n], v0)

else

if Chuaxet[y] then

begin

X[k]:=y;

Chuaxet[y]:=false;

Hamilton(k+1);

Chuaxet[y]:=true;

end;

end;

(* Main program*)

begin

for v ∈ V do Chuaxet[v]:=true;

X[1]:=0; (* v0 la mot dinh nao do cua do thi *)

Chuaxet[v0]:=false;

Hamilton(2);

end.

d. Bài tập tự giải

Bài tập 1: Hội nghị bàn tròn

Tổng thư ký ðại hội ñồng Liên hợp quốc triệu tập một cuộc họp có N nhà

ngoại giao của N tổ chức tham gia. Các ñại diện ngoại giao ñược bố trí ngồi quanh

một bàn tròn. Giữa một số tổ chức có quan hệ căng thẳng, vì vậy không thể xếp họ

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 32

ngồi cạnh nhau ñược. Thông tin về quan hệ giữa các tổ chức ñược cho dưới dạng

cặp số nguyên i, j nếu giữa 2 tổ chức này có quan hệ căng thẳng.

Hãy lập trình giúp Tổng thư ký Liên hợp quốc bố trí chỗ ngồi quanh bàn họp. Các

tổ chức ñược ñánh số từ 1 tới N, 0 < N <= 500.

Dữ liệu vào: từ file CONF.INP, dòng ñầu tiên chứa số nguyên N, các dòng

sau, mỗi dòng một cặp số i, j cho biết các ñại diện i và j không ngồi cạnh nhau

ñược. Kết thúc là một dòng chứa 2 số 0.

Kết quả: ñưa ra file CONF.OUT. Nếu không có cách bố trí thỏa mãn yêu

cầu thì ñưa ra thông báo KHONG CO, trong trường hợp ngược lại – ñưa ra dãy N

số nguyên xác ñịnh vị trí ai ngồi cạnh ai quanh bàn tròn.

Ví dụ:

CONF.INP CONF.OUT

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

1 4

1 7

5 7

10 7

10 8

10 9

3 4

0 0

Bài tập 2: Kiểm tra ñường

Một trạm quảng ñường giao thông phải chịu trách nhiêm về tình trạng của

một mạng lưới giao thông nối giữa các ñiểm dân cư. Hàng tháng, họ phải cử một

ñội ñi kiểm tra một vòng qua khắp mạng lưới ñể xem xét tình trạng hiện thời của

các ñường giao thông nhằm báo sửa chữa kịp thời nếu có nhu cầu. Hãy viết chương

trình nhập vào mạng lưới giao thông và giúp trạm quyết ñịnh lộ trình của ñội kiểm

tra sao cho có thể thăm tất cả các con ñường mà tổng chiều dài ñoạn ñường ñi qua

là nhỏ nhất.

Bài tập 3: Mã ñi tuần

Hãy cài ñặt chương trình xác ñịnh lộ trình của con mã trên bàn cờ 8x8 ô bắt

ñầu từ ô (i, j) ñi qua tất cả các ô của bàn cờ vàmỗi ô chỉ 1 lần duy nhất.

Mở rộng với trường hợp bàn cờ kích thước NxN.

Bài tập 4: Hội nghị bàn tròn

Có 12 người ngồi chung 1 bàn tiệc tròn. Mỗi người có ít nhất 6 người quen.

Hãy chỉ ra cách sắp xếp sao cho mỗi người ñều ngồi cạnh người mình quen . Tổng

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 33

quát, hãy sắp N người ngồi chung quanh bàn tròn sao cho mỗi người ñều ngồi cạnh

người mình quen. Biết mỗi người có ít nhất (N + 1)/2 người quen.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 34

Bài 6 Thuật toán tìm kiếm trên ñồ thị và ứng dụng Mục tiêu

- Trình bày ñược ý tưởng, cách cài ñặt và cài ñặt ñược thuật toán BFS, DFS.

- Nêu ưu nhược của từng thuật toán ñối với từng loại ñồ thị.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

- Rèn luyện tư duy sáng tạo.

a. Nhắc lại lý thuyết

b. ðề bài tập

Bài 1 Dùng cây ñể mô tả kết quả duyệt chiều sâu và duyệt theo chiều rộng trên ñồ

thị sau:

Bài 2 Cho ñồ thị G=(X,E) với tập các ñỉnh X và tập các cung E. Xét xem ñồ thị có

bao nhiêu thành phần liên thông, mỗi thành phần liên thông bao gồm những ñỉnh

nào?

Bài 3 Thuật toán tìm ñường ñi theo chiều sâu (thuật toán duyệt theo chiều sâu)

Bài 4 Thuật toán tìm ñường ñi theo chiều rộng (thuật toán duyệt theo chiều rộng)

c. Hướng dẫn giải

Bài 1 Dùng cây ñể mô tả kết quả duyệt chiều sâu và duyệt theo chiều rộng trên ñồ

thị sau:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 35

Duyệt rộng

Duyệt sâu:

Bài 2 Thuật toán tìm số thành phần liên thông

Cho ñồ thị G=(X,E) với tập các ñỉnh X và tập các cung E. Xét xem ñồ thị có

bao nhiêu thành phần liên thông, mỗi thành phần liên thông bao gồm những ñỉnh

nào?

Phân tích bài toán :

3 5

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 36

8 2 6 3

1

2

2 7 9 2

1 1 3 1

4 1

ðồ thị với các thành phần LT

ðầu vào:

a. Biểu diễn ñồ thị bằng ma trận kề

Dothi.txt Kq.txt

9

0 1 1 1 0 0 0 0 0

1 0 1 0 0 0 0 0 0

1 1 0 1 0 0 0 0 0

1 0 1 0 0 0 0 0 0

0 0 0 0 0 0 0 1 0

0 0 0 0 0 0 1 0 1

So tph cua do thi la:3

TPLT 1 bao gom cac dinh: 1 2 3 4

TPLT 2 bao gom cac dinh: 5 8

TPLT 3 bao gom cac dinh: 6 7 9

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 37

0 0 0 0 0 1 0 0 1

0 0 0 0 1 0 0 0 0

0 0 0 0 0 1 1 0 0

Cấu trúc dữ liệu

ðầu tiên ñánh số các ñỉnh là 0

(Dùng một mảng biểu diễn các thành phần là mảng chúng ta cần tìm, ban ñầu

ta gán tất cả các giá trị của mảng bằng 0)

Lấy ra ñỉnh L gán lt[i]:=1

+ Duyệt các ñỉnh kề của 1 gặp ñỉnh tiếp theo là ñỉnh 2 chưa ñược ñánh số ta

ñánh số 1 gán lt[2]:=1 sang bước tiếp theo.

+ Duyệt các ñỉnh kề của 2, gặp ñỉnh 1 ñược ñánh số rồi nên bỏ qua, gặp ñỉnh

chưa ñánh số nên ñánh số 1, gán lt[4]:=1 sang bước tiếp theo.

+ Duyệt các ñỉnh kề của 4, gặp ñỉnh 1 ñánh số rồi nên bỏ qua. Gặp ñỉnh 2 ñánh

số rồi nên bỏ qua. Gặp ñỉnh 3 chưa ñánh số nên ñánh số 1, lt[3]:=1 sang bước tiếp

theo.

+ Duyệt các ñỉnh kề của 3 gặp toàn các ñỉnh ñánh số rồi nên không ñánh số

nữa dừng việc ñánh số.

Như vậy ta ñã tìm ñược 1 thành phần liên thông.

Lấy ra một ñỉnh chưa ñánh số ví dụ ta lấy ñỉnh 6

Ta lại làm như trên ta lại tìm ñược thành phần liên thông khác.

Như vậy ta rút ra ñược Cấu trúc dữ liệu của bài toán này.

ðối với ñồ thị và các cạnh thì ta có thể dùng ma trận kề hoặc danh sách kề, và

nên ñọc từ file ñể ñơn giản hoá.

Dùng một mảng lt[1…n] biểu diễn TPLT lt[i]:=K nếu ñỉnh i thuộc thành phần

liên thông.

Chương trình minh họa :

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 38

a. Biều diễn ñồ thị bằng ma trận kề.

a(i,j)=1 nếu 2 ñỉnh i và j kề nhau và =0 nếu 2 ñỉnh i và j không kề nhau.

Program tim_thanh_phan_lien_thong;

Const Nmax=100;

Type mang=array[1…Nmax] of integer;

Var lt:mang;

a: array[1…Nmax, 1…Nmax] of byte;

N:integer;

Sotp: integer;

(*Thủ tục này ñọc từ file dothi.txt số N là số ñỉnh của ñồ thị ma trận kề biểu diễn ñồ

thị *)

Procedure Docfile;

Var i,j: integer;

f: text;

Begin

Assign(f,’dothi.txt’);reset(f);

Readln(f,N);

For i:=1 to N do

Read(f,a[i,j]);

Close(f);

End;

(*Thủ tục ñệ quy này dùng ñể tìm các ñỉnh thuộc một thành phần liên thông *)

Procedure Docfile;

Var i,j: integer;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 39

Begin lt[k]:=sotp;

(*Duyệt qua các ñỉnh của ñồ thị *)

For i:=1 to N do

(*Nếu ñỉnh i kề với k và chưa ñánh dấu thì ta gọi thủ tục ñệ quy. Tìm

LT nghĩa là lại ñánh dấu và duyệt các ñỉnh kề của i *)

lf (lt[i]=0)and(a[i,k]=1)then

TimLT(i);

End;

(*Thủ tục này ñược coi như bước 2 trong vớ dụ *)

Procedure TimTPLT;

Var i: integer;

Begin sotp:=0;

(*Duyệt các ñỉnh chưa ñược ñánh dấu *)

For i:=1 to N do

(*Nếu có một ñỉnh chưa thuộc thành phần liên thông nào lt[i]=0 nghĩa

là tìm ra một thành phần mới nên ta tăng số lượng thành phần và bắt ñầu ta ñi

tìm thành phần liên thông mới ñó bằng thủ tục ñệ quy TimLT(i)*)

lf lt[i]=0 then

Begin

Inc(sotp);

TimLT(i);

End;

End;

(*Thủ tục in ra các thành phần liên thông của ñồ thị *)

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 40

Procedure Ghifile;

Var i,j: integer;

Begin

Writeln(‘so thanh phan lien thong cua do thi lµ: ;sotp);

For i:=1 to sotp do

Begin

Writeln(‘TPLT’, i ,’bao gom cac dinh:’);

For j:=1 to N do

(*nếu j thuộc thành phần liên thông thứ i thì in ra *)

lf lt[j]=i then

Write(J,’ ‘);

Writeln;

End;

Readln;

End;

BEGIN

Docfile;

Tim TPLT;

Ghifile;

END.

b. Biểu diễn ñồ thị bằng danh sách cạnh

Ma trận của chúng ta (ở ví dụ trên) ñược viết dưới dạng:

2 3 4 9

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 41

1 3 0 1 2 3 4

2 4 0 2 1 3

1 3 0 3 2 4

8 0 0 4 1 3

7 9 0 5 8

6 9 0 6 7 9

5 0 0 7 6 9

6 7 0 85

9 6 7

a[i,9] là số lượng các ñỉnh kề với ñỉnh i;

a[i,j] chính là các ñỉnh kề với các ñỉnh i (j=1,2,3,…)

Khi ñó thủ tục Docfile ñược viết lại như sau:

Procedure Docfile;

Var i,j,t: integer;

f: text;

Begin Assign(f,’dothi.txt’);reset(f);

Readln(f,N);

For i:=1 to sotp do

Bengin

Read(f,t);

While not eoln(f) do

Begin

Read(f,t);

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 42

Inc(j);

a[i,j]:=t;

End;

a[i,0]:=j;

End;

Close(f);

End;

Thủ tục Ghifile và thuc tục TimTPLT không có gì thay ñổi

Thủ tục TimTPLT thay ñổi như sau:

Procedure TimLT (k:integer);

Var i: integer;

Begin

Lt[k]:=sotp;

For i:=1 to a[k,0] do

If lt[a[k,i]]=0 then

TimLT(a[k,i]);

End;

Bài 3 ðề bài : Thuật toán tìm ñường ñi theo chiều sâu (thuật toán duyệt theo chiều

sâu).Tìm ñường ñi giữa hai ñỉnh xp và kt trên ñồ thị G vô hướng và không có trọng

số.

Phân tích bài toán :

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 43

Thuật toán của bài toán này cũng giống như thuật toán tìm thành phần liên

thông của ñồ thị. Trong phần Cấu trúc dữ liệu có dùng mảng trước ñể lưu ñường ñi

từ ñỉnh xp ñến ñỉnh kt.

Chương trình minh họa :

Program Duyetchieusau;

Const Nmax=100;

Type Mang=array[1…Nmax] of integer;

Matran= array[1…Nmax,1…Nmax] of integer;

Var a:Matran;

so,duong:mang;

N:integer;

(*thủ tục ñọc tệp và ghi tệp giống như bài trước chỉ ñọc thêm hai ñỉnh xp và kt

*)

Procedure Duyet (k:integer);

Var i:integer;

Begin

For i:=1 to N do

(*Duyệt các ñỉnh kề với k *)

lf (a[i,k]=1)and(truoc[i]=0)then

Begin (*ta gán ñỉnh ñã ñi trước ñỉnh i là ñỉnh k *)

Truoc[i]:=k;

Duyet(i);

End;

End;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 44

Procedure Duyetsau;

Var i:integer;

Begin

For i:=1 to N do truoc[i]:=0

Truoc[xp]:=-1;

Duyet(xp);

End;

Procedure Timduong;

(*thủ tục này giống thủ tục tìm ngược trong duyệt chiều rộng, nhưng chỉ tìm

một ñường ñi ngắn nhất trong rất nhiều ñường ñi ngắn nhất từ xp ñến kt *).

Var i,u: integer;

Begin

sold:=0;

u:=kt;

REPEAT

Inc(sold);

Duong[sold]:=u;

U:=truoc[u];

UNTIL u=-1;

End;

BEGIN

Doctiep;

Duyetsau;

Timduong;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 45

Ghitep;

END.

Bài 4 ðề bài : Thuật toán tìm ñường ñi theo chiều rộng (thuật toán duyệt theo chiều

rộng). Cho ñồ thị vô hướng G=(X,E). Hãy tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và

kt cho trước (ñường ñi ngắn nhất là xích có 2 ñầu là xp và kt và ñi qua ít cung hoặc

ít ñỉnh nhất).

Phân tích bài toán

Sử dụng hàng ñợi ñể giải quyết bài toán này. Cách ñưa một ñỉnh của ñồ thị và

lấy 1 ñỉnh ra sử dụng phải tuân theo một quy tắc nhất ñịnh.

Sử dụng một mảng ñánh dấu ñường ñi truoc: array[1..Nmax] of integer

Khi ñi từ ñỉnh xp mà muốn có ñường ñi ngắn nhất ñến u thì ta phải qua ñỉnh

truoc [u], muốn có ñường ñi ngắn nhất ñến truoc [u] thì ta phải ñi qua truoc [truoc

[u] ],…

Yêu cầu: Sau thủ tục duyệt theo chiều rộng thì ta phải tìm ñược mảng truoc.

Khởi tạo giá trị ban ñầu của mảng truoc bằng 0.

B1: Khởi tạo hàng ñợi.

ðưa xp vào hàng ñợi. Gán truoc [xp]: = -1

B2: REPEAT

Lấy 1 ñỉnh ra khỏi hàng ñợi. Giả sử ñỉnh u.

Duyệt những ñỉnh kề với u, giả sử duyệt ñến ñỉnh v.

- Nếu trước [v] = 0 thì ta ñưa v vào hàng ñợi ñồng thời gán truoc [v]: = u.

Nghĩa là muốn ñi qua v thì phải ñi qua ñỉnh trước ñó là u;

B3: Kiểm tra v có phải là kt hay không, nếu có thì thoát khỏi thủ tục;

Nếu truoc [v] <> 0 thì bỏ qua.

UNITL (hàng ñợi rỗng) or (truoc [kt]<>0

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 46

Hàng ñợi rỗng nghĩa là không còn ñỉnh nào ở trong hàng ñợi.

Trên ñây là sườn của thủ tục duyệt chiều rộng, nếu sau những bước này mà

truoc [kt] = 0 nghĩa là không tồn tại ñường ñi từ xp ñến kt.

B4: (Tim ñường ñi thông qua mảng truoc)

Dùng một mảng duong: array [1..Nmax] of integer ñể biểu diễn các ñỉnh nằm

trên ñường ñi. Mảng này thể hiện ñường ñi ngược từ kt về xp. Do ñó khi in kết quả

ra màn hình ta phải in ngược từ cuối mảng.

Khởi ñầu u: = kt;

sold: = 0 (số lượng ñỉnh trên ñường ñi khởi ñầu bằng 0)

REPEAT

Tăng sold lên 1 ñơn vị

gán duong [sold]: = u;

ñi ngược lại bước trước u: = truoc [u];

UNILT u = -1

B5: In kết quả.

Thuật toán hơi khó hiểu. Bạn sẽ thấy rõ trong phần cài ñặt chương trình.

Cấu trúc dữ liệu

Mảng 2 chiều a (ij) biểu diễn ma trận liên thuộc các ñỉnh và các cung của ñồ

thị.

Mảng truoc và mảng duong mô tả như trên.

Mảng q (quene) mô tả cấu trúc của hàng ñợi.

Thủ tục

Program Duyet _chieu_rong;

Const Nmax = 100;

Type mang = array [1..Nmax] of integer;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 47

Var q,truoc,duong:mang;

A:array [1..Nmax, 1..Nmax] of byte;

Sold; N,xp,kt,qf,ql: integer;

(* qf- queue first là con chạy ñầu hàng ñợi

ql-queue last là con chạy cuối hàng ñợi*)

Chương trình minh họa :

Procedure Docfile;

Var ij: integer;

f: text;

Begin

Assign (f, ‘dothi.txt’); reset (f);

Readln (f,N);

For i:= 1 to N do

Forj:= 1 to N do

Read (f,a[ i j]);

Close(f);

Readln (f,xp,kt);

End;

(*Thủ tục khởi ñộng hàng ñợi *);

Procedure InitQ;

Begin

ql: = 1

qf: = 0

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 48

End;

(*Thủ tục ñưa một ñỉnh vào cuối hàng ñợi *)

Prcedure Put (k:integer);

Begin

q[ql]: = k;

inc (ql);

End;

(*Hàm lấy một ñỉnh ra khỏi hàng ñợi – lấy ở ñầu hàng ñợi*)

Function Get:integer;

Begin

Get:= q[qf];

inc (qf);

End;

(*Hàm kiểm tra hàng ñợi rỗng hay không*)

Function Qempty: Boolean;

Begin

Qempty: = (qf>ql);

End;

(*Thủ tục duyệt chiều rộng *)

Procedure DuyetCR;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 49

Var v,u:integer;

Begin InitQ;

Put (xp;

Truoc [xp]: = -1;

REPEAT

U: = Get;

(Duyệt các ñỉnh kề của u*)

For v: = 1 to N do

If (a[u,v] = 1 and (truoc [v]= 0) then

Beign

(*Nếu v kề với u và chưa ñi qua thì ñánh dấu và ñưa v vào hàng ñợi*)

Truoc [v]: = u;

Put (v);

End;

UNILT Qempty or (truoc [kt] <>0);

End;

(*Thủ tục tìm mảng ñường ñi từ xp ñến kt ở dạng ngược *)

Procedure Timduong;

Var u:integer;

Begin sold: = 0;

u:= kt;

REPEAT

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 50

inc (sold);

Duong[sold]:=u;

u:=truoc[u]:

UNILT u = xp;

End;

(*Thủ tục in kết quả ra màn hình *)

Procedure Inkq;

Var i:integer;

Begin

If truoc[kt]= 0 then

Writeln (‘khong co duong di tư ‘,xp, ‘den’, kt)

else

Begin Writeln (‘Duong di tư ‘, xp, ‘den’, kt);

(*Khi in phải in ngược mảng ñường từ sold trở về 1*)

For i: = sold downto 1 do

Write (duong[i], ‘ ‘);

End;

Realn;

End;

BEGIN

Docfile;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 51

Duyet CR;

(*Chắc chắn rằng nếu có ñường ñi ñến ñỉnh kt thì ta mới tìm mảng ñường *)

If truoc[kt]<>0 then

Timduong;

Inkq;

END.

d. Bài tập tự giải

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 52

Bài 7: Cây và cây khung Mục tiêu

Mục tiêu của bài này người học có khả năng:- Xác ñịnh ñược một ñường ñi, một

chu trình trong ñồ thị bất kỳ.

- Biểu diễn ñồ thị trên máy tính bằng các phương pháp khác nhau.

- Áp dụng ñược thuật toán Kruskal và Prim ñể tìm cây khung nhỏ nhất ứng với một

ñồ thị xác ñịnh. Cài ñặt ñược thuật toán.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

Các ñịnh nghĩa: ñồ thị, cạnh, cung, ñỉnh kề, cây, cây khung.

Các phương pháp biển diễn ñồ thị trên máy tính

ðịnh lý 3.4.2: Cho T là một ñồ thị có n ≥ 2 ñỉnh. Các ñiều sau là tương ñương:

1) T là một cây.

2) T liên thông và có n−1 cạnh.

3) T không chứa chu trình và có n−1 cạnh.

4) T liên thông và mỗi cạnh là cầu.

5) Giữa hai ñỉnh phân biệt bất kỳ của T luôn có duy nhất một ñường ñi sơ cấp.

6) T không chứa chu trình nhưng khi thêm một cạnh mới thì có ñược một chu

trình duy nhất.

Bài toán cây khung nhỏ nhất

Thuật toán Kruskal với ý tưởng “chọn dần”

B1: Chọn cạnh trọng số nhỏ nhất

B2: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại

B3: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại, mà ko tạo thành chu

trình.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 53

Lặp lại bước 3 cho tới khi chọn ñược n-1 cạnh.

Thuật toán Prim với ý tưởng “lan tỏa”. Giả sử lan tỏa từ ñỉnh A

B1: Chọn cạnh trọng số nhỏ nhất thuộc A (tức có 1 ñầu là ñỉnh A)

Giả sử là cạnh (A,B)

B2: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại thuộc A hoặc B (tức có

1 ñầu là ñỉnh A hoặc B). Giả sử là cạnh (C,B) hoặc (C,A)

B3: Chọn cạnh trọng số nhỏ nhất trong các cạnh còn lại thuộc A hoặc B hoặc

C, mà ko tạo thành chu trình.

Lặp lại bước 3 cho tới khi chọn ñược n-1 cạnh.

b. ðề bài tập

Bài tập 1: Cho ñồ thị vô hướng có trọng số sau:

Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung), danh sách lien kết.

Áp dụng thuật toán Prim( xuất phát tại ñỉnh 1) hoặc Kruskal tìm cây khung nhỏ nhất

cho ñồ thị trên.

Bài 2 Áp dụng thuật toán Kruskal ñể tìm cây khung nhỏ nhất của ñồ thị cho trong

hình dưới ñây:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 54

c. Hướng dẫn giải

Bài tập 1:

- Thuật toán Prim với ý tưởng “lan tỏa”, xuất phát từ ñỉnh 1 “lan tỏa” ta có các cạnh

tạo thành cây khung nhỏ nhất lần lượt là: (1,5); (5,4);(4,2) và (4,3)

Gọi V(E) là tập các ñỉnh(cạnh) của ñồ thị,

Vt(Et) là tập các ñỉnh(cạnh) của cây khung nhỏ nhất cần tìm.

Thuật toán Prim với các bước thứ tự ñược miêu tả trong bảng sau:

Bước E Et Vt

Khởi tạo {} {1}

1 {(1,5)} {1,5}

2 { (1,5); (5,4); } {1,5,4}

3 { (1,5); (5,4);(4,2) } {1,5,4,2}

4 { (1,5); (5,4);(4,2) và

(4,3) }

{1,5,4,2,3}=V => dừng

Chú ý:

Thuật toán Kruskal với ý tưởng “chọn dần” các ñỉnh có trọng số nhỏ nhất trong các

cạnh còn lại, nếu ko tạo thành chu trình. Quá trình lặp lại cho tới khi chọn ñược n-1

cạnh.

Các cạnh ñược chọn ñể tạo thành cây khung nhỏ nhất lần lượt là: (2,4);(4,5);(4,3) và

(1,5)

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 55

- Thuật toán Prim với ý tưởng “lan tỏa”, xuất phát từ ñỉnh 4

“lan tỏa” ta có các cạnh tạo thành cây khung nhỏ nhất lần lượt là: (4,2);(4,5);(4,3)

và (1,5)

Với các bước thứ tự (tự làm)

Bài 2:

Bước khởi tạo. ðặt T:=Æ . Sắp xếp các cạnh của ñồ thị theo thứ tự không giảm của

ñộ dài ta có dãy:

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

dãy ñộ dài tương ứng của chúng

4, 8, 9, 14, 16, 17, 18, 20, 23.

Ở ba lần gặp ñầu tiên ta lần lượt bổ sung vào tập T các cạnh (3,5) , (4,6) , (4,5). Rõ

ràng nếu thêm cạnh (5,6) vào T thì sẽ tạo thành 2 cạnh (4,5), (4,6) ñã có trong T chu

trình. Tình huống tương tự cũng xảy ra ñối với cạnh (3,4) là cạnh tiếp theo của dãy.

Tiếp theo ta bổ sung cạnh (1,3), (2,3) vào T và thu ñược tập T gồm 5 cạnh:

T = { (3,5) , (4,6) , (4,5) , (1,3) , (2,3) }

Chính là tập cạnh của cây khung nhỏ nhất cần tìm.

d. Bài tập tự giải

Bài tập 1: Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung), danh sách lien

kết.

Áp dụng thuật toán Prim và Kruskal tìm cây khung nhỏ nhất cho ñồ thị sau:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 56

Bài tập 2 : Mạng an toàn

Cho một mạng N (N <= 20) máy tính ñược ñánh số từ 1 ñến N. Sơ ñồ mạng

ñược cho bởi hệ gồm M kênh (ñoạn) nối trực tiếp giữa một số cặp máy trong mạng,

m kênh tương ứng với m cặp. Cho biết chi phí truyền 1 ñơn vị thông tin theo mỗi

kênh của mạng.

Người ta cần chuyển một bức thông ñiệp từ máy s ñến máy t. ðể ñảm bảo an

toàn, người ta chuyển bức thông ñiện này theo hai ñường truyền tin khác nhau (tức

không có kênh nào) của mạng ñược sử dụng trong cả hai ñường truyền tin; cho phép

hai ñường truyền tin cùng ñi qua một số máy tính). Chi phí của một ñường truyền

ñược hiểu là tổng chi phí trên các kênh của nó. ðơn giá ñường truyền từ máy s sang

máy t ñược tính như sau:

Với hai máy s và t, cùng bức thông ñiệp có ñộ dài là 1 ñơn vị thông tin, ñơn

giá truyền cho cặp (s, t) ñược tính bằng tổng chi phí chuyển thông ñiệp an toàn

(bằng tổng chi phí của hai ñường truyền tin) là nhỏ nhất.

Mạng truyền tin nói trên thỏa mãn tính chất an toàn theo nghĩa là từ một máy

bất kỳ luôn truyền ñược (một cách an toàn) thông ñiệp tới một máy bất kỳ khác. Khi

một mạng an toàn, người ta tính ñược ñơn giá của mạng là tổng ñơn giá mọi ñường

truyền từ một máy bất kỳ tới một máy bất kỳ khác.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 57

Ma trận ñơn giá của mạng là mảng hai chiều A có N dòng và N cột, mà giá

trị phần tử A[i, j] chính là ñơn giá từ máy i sang máy j.

Câu 1: Cho trước một mạng, hãy kiểm ra tính an toàn của mạng ñó.

Câu 2: Khi mạng không an toàn ñược phép bổ sung một số kênh truyền ñể

nó trở thành an toàn. ðơn giá mỗi kênh truyền bổ sung theo ñược coi bằng hai lần

giá trị cực ñại ñơn giá các kênh ñã có. Mọi kênh bổ sung ñược coi có ñơn giá như

nhau. Hãy tìm cách bổ sung các kênh mới mà ñơn giá mạng là nhỏ nhất.

Câu 3: Khi mạng an toàn hoặc sau khi bổ sung kênh ñể mạng an toàn, hãy in

ra ñơn giá mạng và ma trận ñơn giá.

Dữ liệu vào: cho trong file INP.B2 với cấu trúc như sau:

Dòng ñầu tiên ghi 2 số n, m cách nhau bởi dấu cách.

Mỗi dòng thứ i trong số m dòng tiếp theo ghi thông tin về kênh nối thứ i của

mạng gồm 3 số d[i], c[i], g[i] trong ñó d[i], c[i] là chỉ số của hai máy tương ứng với

kênh này và g[i] (nguyên dương) là chi phí ñể truyền một ñơn vị thông tin từ máy

d[i] ñến máy c[i] theo kênh này. Các giá trị g[i] cho trước không vượt quá 40 (và

như vậy ñơn giá các kênh bổ sung không vượt quá 80).

Kết quả: ghi ra file OUT.B2 theo qui cách sau:

Dòng ñầu tiên ghi 1 số nguyên p thể hiện mạng có an toàn hay không và p có ý

nghĩa là số lượng kênh cần bổ sung. p=0 có nghĩa mạng an toàn; p>0 có nghĩa mạng

không an toàn và cần bổ sung p kênh nữa ñể mạng an toàn với chi phí bổ sung ít

nhất.

p dòng tiếp theo ghi p kênh bổ sung. Cách ghi như trong file dữ liệu vào.

Dòng tiếp theo ghi ñơn giá của mạng an toàn.

N dòng tiếp theo ghi ma trận ñơn giá của mạng an toàn: mỗi hàng của ma

trận ghi trên một dòng.

Bài tập 3: Xây dựng ñường ống nước

Có 1 trạm cấp nước và N ñiểm dân cư. Hãy xây dựng chương trình thiết kế tuyến

ñường ống nước cung cấp ñến mọi nhà sao cho tổng chiều dài ñường ống phải dùng

là ít nhất. Giả sử rằng các ñường ống chỉ ñược nối giữa 2 ñiểm dân cư hoặc giữa

trạm cấp nước với ñiểm dân cư.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 58

Bài 8: Thảo luận về cài ñặt thuật toán tìm cây khung nhỏ nhất trên ñồ thị Mục tiêu

- Cài ñặt ñược thuật toán xây dựng tập các chu trình cơ bản.

- Cài ñặt ñược thuật toán Prim, Kruskal ñể ñưa ra cây khung nhỏ nhất của ñồ thị cho

trước.

- Mở rộng ý tưởng, mở rộng thuật toán Prim.

- Cài ñặt ñược thuật toán xây dựng tập các chu trình cơ bản.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

- Rèn luyện tư duy sáng tạo.

a. Nhắc lại lý thuyết

b. ðề bài tập

Bài 1 Tìm cây bao trùm nhỏ nhất của ñồ thị G dung thuật toán Kruskal

Bài 2 Tìm cây bao trùm nhỏ nhất của ñồ thị G dung thuật toán Prim

c. Hướng dẫn giải

Bài 1 ðề bài : Tìm cây bao trùm nhỏ nhất của ñồ thị G

Phân tích bài toán :

Trước hết ta phải xét ví dụ sau:

8 3

2

1 7 2 3 7

5

1 8

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 59

2 1

4 1 7 6

6 1 9

Tư tưởng của thuật toán là ñưa từng cạnh vào cây bắt ñầu từ những cạnh có trọng số

nhỏ nhất và làm cho ñến khi cây bao gồm tất cả các ñỉnh của ñồ thị.

Giả sử T là cây bao trùm cần tìm. Và tập V là tập bao gồm các tập Gi có tính chất

như sau:

- Gi có phần tử là các ñỉnh của ñồ thị mà chúng ñược nối với nhau bởi các cạnh ñã

ñược ñưa vào T. Từ một ñỉnh thuộc Gi luôn có ñường ñi ñến một ñỉnh khác cũng

thuộc Gi.

- Giao của Gi và GJ bẵng rỗng.

Với ñịnh nghĩa như trên ta nhận thấy rõ ràng rằng mỗi một tập Gi thuộc tập V là

một cây bao trùm con nhỏ nhất. Như vậy thuật toán của chúng ta như một bài toán

quy nạp là gộp nhưng cây bao trùm này thành những cây trùm lớn hơn cho ñến khi

nó gồm tất cả các ñỉnh của ñồ thị và ñương nhiên ta phải nối những cây bao trùm Gi

này bằng những cạnh có trọng số nhỏ nhất. Kết thúc khi V = { {1,2,3…,n} } = {X};

Ban ñầu:

+ Cây bao trùm của ñồ thị là rỗng nghĩa là chưa có cạnh nào ñược ñưa vào cây bao

trùm. (T = ỉ ).

+ Gi chính là những ñỉnh của ñồ thị => V = { {1}, {2}, {3}…,{n} }

Thuật toán ñược viết cụ thể với ví dụ trên như sau:

- Khởi tạo T = { }

V = { {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} }

- ðưa cạnh nhỏ nhất (1,2) vào cây khi ñó 1 ñược nối với 2 nên thay {1} và {2}

trong V bằng {1,2}

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 60

T = { (1,2) }

V = { {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9} }

- ðưa cạnh (4,5) vào cây:

T = { (1,2); (4,5)}

V = { {1,2}, {3}, {4,5}, {5}, {6}, {7}, {8}, {9} }

- ðưa cạnh (5,6) vào cây:

T = {(1,2); (4,5); (5,6)}

V = { {1,2}, {3}, {4,5,6}, {7}, {8}, {9} }

- ðưa cạnh (6,9) vào cây:

T = {(1,2); (4,5); (5,6); (6,9)}

V = { {1,2}, {3}, {4,5,6,9}, {7}, {8} }

- ðưa cạnh (1,4) vào cây:

T = {(1,2); (4,5); (5,6); (6,9); (1,4)}

V = { {1,2,4,5,6,9}, {3}, {7}, {8} }

- ðưa cạnh (5,7) vào cây:

T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7)}

V = { {1,2,4,5,6,9}, {3}, {8} }

- ðưa cạnh (3,5) vào cây:

T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7); (3,5)}

V = { {1,2,3,4,5,6,7,9}; {8} }

- ðưa cạnh (7,8) vào cây:

T = {(1,2); (4,5); (5,6); (6,9); (1,4); (5,7); (3,5); (7,8)}

V = { {1,2,3,4,5,6,7,8,9} }

Kết thúc vì V = {X};

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 61

Chú ý: Thứ tự chọn các cạnh ñưa vào cây là ưu tiên các cạnh có trọng số bé hơn.

Cấu trúc dữ liệu

Ta biểu diễn ñồ thị dưới dạng liệt kê các cung (chỉ áp dụng cho ñồ thị nhỏ)

Như vậy dung một mảng hai chiều:

e: array [1…Emax, 1..3] of Integer

với e [i,3] là trọng số của cung (e[i,1], e[i,2],…,emax)

Mảng T: array [1…Emax, 1..2] of Integer biểu diễn các cạnh ñược ñưa vào T.

Dùng biến solT ñể xác ñịnh số lượng cạnh ñã ñưa vào cây T;

(khởi tạo solT: = 0 nghĩa là cây T = ỉ)

Biểu diễn V là tập hợp của các tập hợp rất phức tạp, do ñó ta dùng một Cấu trúc dữ

liệu ñơn giản ñể mô phỏng tập V như sau:

Mảng tap V: array[1…Nmax] of integer

Trong ñó hai ñỉnh i và j thuộc cùng một tập Gk nào ñó nếu như tap V[i] = tap [j]

Như vậy ban ñầu giá trị của mảng tapV là tapV[i] gán bằng i;

ở mỗi bước khi ta ghép các ñỉnh của 2 tập Gk và Gh thành một tập thì ta chỉ việc gán

cả các giá trị của tập Gk bằng giá trị của tập Gh.

Ví dụ với N = 10;

ở một bước nào ñó

mảng tapV = [ 1,2,2,6,6,2,1,4,4,10]

ta hiểu là V = { {1,7}; {2,3,6}, {4,5}, {8,9}, {10} }

ñến bước tiếp theo ta ñưa cạnh (4,6) vào cây nghĩa là cần gộp 2 tập {2,3,6 }và {4,5}

thành một. Ta gán tapV[4] = tapV[2;]

tapV[5] = tapV[2;];

Khi ñó mảng tapV = [1,2,2,2,2,2,1,4,4,10]

ðiều này rất có lợi khi ta gộp hai tập hợp con với nhau.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 62

Với toàn bộ dữ liệu ñược mô tả như trên ta có phần cài ñặt chương trình:

Chương trình minh họa :

Program kruskal;

Const Nmax = 100;

Emax = 1000;

Type mangcanh = array [1..Emax, 1..2] of integer;

Dinh = array [1…Nmax] of integer;

Var e,T; Mangcanh;

TapV: Dinh;

N, solE, solT: integer;

(*solE là số cạnh của ñồ thị còn solT là số cạnh ñược ñưa vào T*)

Prrocudure Doctep;

(* Dữ liệu vào gồm có:

- Dòng ñầu tiên chứa số N

- Từ dòng thứ hai trở ñi mỗi dòng chứa 3 số nguyên là 2 ñỉnh của một cạnh và trọng

số của cạnh ñó.

*)

Var f: text;

i,j,k: integer;

Begin Assign (f’, cung.txt’); Reset(f);

Readln (F,N);

SolE: = 0;

While not eof(f) do

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 63

begin Read (f,i,j,k);

Inc(solE);

e[solE,1]: = i;

e[solE,2]: = j;

e[solE,3]: = k;

End;

Close (f);

End;

Procedure Sapxep;

(*Dùng phương pháp sắp xếp nổi bọt ñể sắp xếp các cạnh theo thứ tự trọng số từ

nhỏ tới lớn(*)

Var ij : integer;

Beign

For i:= 1 to solE-1 do

For j:= i + 1 to solE do

If e[i,3] > e[j,3] then

Doicho(i,j);

End;

Procedure Doicho (i,j;integer);

Var temp: integer;

Begin

Temp: = e[i,1];

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 64

e[i,1]: = e[j,1];

e[j,1]: Temp;

Temp: = e[i,2];

e[i,2]: = e[j,2];

e[j,2]: = Temp;

Temp: = e[i,3];

e[i,3]: = e[j,3];

e[j,3]: = Temp;

End;

Procedure TimCay:

Var i,k, temp:integer;

Begin

solT: = 0; (*T = ỉ*)

For i: = 1 to N do

TapV [i]: = i;

K: = 0;

While (not KttapV) and (K<solE) do

(*Chừng nào tapV còn chưa ñồng nhất các giá trị *)

Begin

Inc (k);

(*ðưa cung thứ k vào cây T*)

If tapV [e,k,1] <> tapV [e [k,2] ] then

(* Nếu 2 ñỉnh e[k,l] và e[k,2] chưa thuộc cùng 1 cây con thì ta mới ñưa vào cây T

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 65

và thực hiện tiếp. Ngược lại thì bỏ qua cạnh này ñể tránh tạo thành chu trình trong

cây*)

Begin

Inc(solT);

T [solT,1]: = e[k,1];

T [solT,2]: = e[k,2];

(* ðồng nhất giá trị trong 2 tập con chứa 2 ñỉnh e[k,1] và e[k,2] của V*). ðưa cạnh

vào cây khung.

temp: = tapV [ e[k,2] ];

For i: = 1 to N do

If tapV [i] = temp then

TapV [i]: = TapV [ e[i,2] ];

End;

End;

End;

Function KTtapV: Boolean;

(*Hàm kiểm tra xem các giá trị của tập V có bằng nhau hay không*)

Var i: integer;

Begin KTtapV: = True;

For i: = 2 to N do

If tapV [i] <> tapV [i] then

Begin KTtapV: = False;

Exit;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 66

End;

End;

Procedure GhiTep;

(*Ta chỉ việc ñưa cây T ra màn hình*)

Var i: integer;

begin

Writeln (‘ Cac cung thuoc cay bao trum nho nhat T la:’)

For i: = 1 to solT do

Writeln (T [i, l]; ‘ ‘; T[i,2];

Readln;

End;

BEGIN

DocTep;

Sapxep;

TimCay;

GhiTep;

END.

Bài 2 ðề bài : Tìm cây bao trùm nhỏ nhất của ñồ thị G

Phân tích bài toán :

Giả sử T là cây bao trùm tối thiểu cần xây dựng. Giả xử ta bắt ñầu từ ñỉnh u.

Gọi U là tập các ñỉnh kề với các ñỉnh có cung nối với cây T;

Khởi tạo U = u;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 67

T = ỉ;

B1: Chọn (u,v) là cạnh có trọng số bé nhất với u

B2: ðưa ñỉnh v vào tập U;

B3: Nếu U = X thì kết thúc; ngược lại thì quay lại bước 1;

Cấu trúc dữ liệu

Ta biểu diễn ñồ thị dưới dạng liệt kê các cung (chỉ áp dụng cho ñồ thị nhỏ)

Như vậy dung một mảng hai chiều:

e: array [1…Emax, 1..3] of Integer

với e [i,3] là trọng số của cung (e[i,1], e[i,2],…,emax)

Mảng T: array [1…Emax, 1..2] of Integer biểu diễn các cạnh ñược ñưa vào T.

Dùng biến solT ñể xác ñịnh số lượng cạnh ñã ñưa vào cây T;

(khởi tạo solT: = 0 nghĩa là cây T = ỉ)

Biểu diễn V là tập hợp của các tập hợp rất phức tạp, do ñó ta dùng một Cấu trúc dữ

liệu ñơn giản ñể mô phỏng tập V như sau:

Mảng tap V: array[1…Nmax] of integer

Trong ñó hai ñỉnh i và j thuộc cùng một tập Gk nào ñó nếu như tap V[i] = tap [j]

Như vậy ban ñầu giá trị của mảng tapV là tapV[i] gán bằng i;

ở mỗi bước khi ta ghép các ñỉnh của 2 tập Gk và Gh thành một tập thì ta chỉ việc gán

cả các giá trị của tập Gk bằng giá trị của tập Gh.

Ví dụ với N = 10;

ở một bước nào ñó

mảng tapV = [ 1,2,2,6,6,2,1,4,4,10]

ta hiểu là V = { {1,7}; {2,3,6}, {4,5}, {8,9}, {10} }

ñến bước tiếp theo ta ñưa cạnh (4,6) vào cây nghĩa là cần gộp 2 tập {2,3,6 }và {4,5}

thành một. Ta gán tapV[4] = tapV[2;]

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 68

tapV[5] = tapV[2;];

Khi ñó mảng tapV = [1,2,2,2,2,2,1,4,4,10]

ðiều này rất có lợi khi ta gộp hai tập hợp con với nhau.

Tập U là tập các ñỉnh có cung nối với T, khai báo T,X: set of 1…Nmax;

Các thành phần dữ liệu khác khai báo giống như phần trước.

Program Prim;

Const Nmax = 100;

Emax = 1000;

Type mangcanh = array [1…Emax, 1...3]of integer;

Tap = set of 1…Nmax;

Var e,T: Mangcanh;

VT X: Tap; {X: Tập ñỉnh của ñồ thị; VT: Tập ñỉnh của cây}

N, solE, solT: integer;

(*Thủ tục ñọc file và ghi file tương tự như trên*)

Procedure Timcay;

Var k,i,j: integer;

TrongsoMin: Longint;

Begin

solT: = 0; VT = [xp]

X: = [ ];

For i: = 1 to N do

X: = X + [i];

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 69

REPEAT

(*Tìm cạnh (u,v) sao cho u và có trọng số nhỏ nhất *)

TrongsoMin: = MaxLongint;

For k: = 1 to solE do

Begin

If (e[k,l] in VT and not e[k,2] in VT and (e[k,3] < TrongsoMin)

then

Begin

i: = e[k,1];

j: = e[k,2];

TrongsoMin: = e[k,3;

End;

If not e[k,1] in VT and (e[k,2] in VT and (e[k,3] < TrongsoMin)

then

Begin

i: = e[k,2];

j: = e[k,1];

TrongsoMin: = e[k,3];

End;

(*ðưa j vào tập U*)

vT = VT + [j];

(*ðưa cạnh (i,j) vào cây T*)

inc(solT);

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 70

T [solT,1]: = i;

T [solT,2]: = j;

UNILT U = X;

End;

BEGIN

Docfile;

Timcay;

Ghifile;

END.

d. Bài tập tự giải

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 71

Bài 9, 10: Bài toán tìm ñường ñi ngắn nhất Mục tiêu

Mục tiêu của bài này người học có khả năng:- Biểu diễn ñồ thị trên máy tính bằng

các phương pháp khác nhau.

- Áp dụng ñược thuật toán ford-bellman và dijkstra tìm ñường ñi ngắn nhất ứng với

một ñồ thị xác ñịnh. Cài ñặt ñược thuật toán.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

Thuật toán dijkstra với ý tưởng “lan tỏa” và lưu 1 chỉ số tại mỗi ñỉnh.

ðể tìm lại ñường ñi ngắn nhất, ta lưu cả tên ñỉnh liền kề trước nó trên ñường ñi

ngắn nhất.

b. ðề bài tập

Bài tập 1: Biểu diễn ñồ thị dạng ma trận kề, danh sách cạnh(cung).

Áp dụng thuật toán Dijkstra tìm ñường ñi ngắn nhất từ ñỉnh 5 tới các ñỉnh còn lại

cho ñồ thị sau:

Bài2 Tìm ñường ñi ngắn nhất từ 1 ñến các ñỉnh còn lại của ñồ thị

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 72

Bài 3 ðưa thư

Nhà bác ñưa thư có việc bận, bác ñưa thư rất sốt ruột muốn về nhà ngay

nhưng bác phải ñưa một thư quan trọng cho anh B ở quận Ba ðình. Hiện tại

bác ở quận Thanh Xuân. ðường ñi từ chỗ bác tới nhà anh B phải ñi qua một số

quận huyện khác với khoảng cách giữa các quận như sau. Hãy giúp bác ñưa

thư tìm ñường ñi ngắn nhất với thời gian ít nhất ñể bác có thể về nhanh chóng

giải quyết công việc gia ñình.

Bài 4 Hổ bắt mồi

Một con hổ ñứng trên ñồi cao nhìn xuống khu rừng và phát hiện ra 5 con mồi

ở 5 vị trí khác nhau. Con hổ muốn bắt con Nai trong số 5 con vật ñó là Nai, Gà,

Hươu, Thỏ, Bò ñể ăn thịt. Khi con Hổ muốn bắt con Nai ñó, nó phải chạy qua

ñường mà 4 con vật còn lại ñang ñứng. Vị trí và khoảng cách mà các con vật

ñược biểu diễn như sau. Tìm ñường ñi ñể quãng ñường mà con Hổ phải chạy

là ngắn nhất ñể bắt ñược con Nai.

Bài 5 Mèo bắt chuột

Mèo Tom(1) rình chú chuột nhỏ Jeny(4) ñang ăn trộm phomat. Từ chỗ Tom ñến

Jeny có cái xô nước(2), chậu cây cảnh (3), ghế sofa(5) với thời gian ñể Tom chạy

ñến các ñồ vật trên và giữa các ñồ vật cũng như thời gian Tom chạy từ các ñồ vật

ñến Jeny như sau: xô nước chậu cây cảnh

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 73

Tom Jeny

ghế sofa

Tom có thể chạy ñến nấp ở chỗ các ñồ vật trên ñể rình và bắt Jeny. Tìm thời gian

nhỏ nhất ñể Tom chạy ñến bắt Jeny mà không bị Jeny phát hiện(nhờ nấp vào các ñồ

vật có trên ñường ñi)

Bài 6 Cho ñồ thị có trọng số G = (X,E). Tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và

kết thúc của ñồ thị

c. Hướng dẫn giải

Bài 1:

Biểu diễn ñồ thị dạng ma trận kề như sau:

0 18 M 13 12

18 0 11 3 M

M 11 0 5 9

13 3 5 0 4

12 M 9 4 0

Dùng thuật toán Dijkstra giảm trọng số 1 lần tại mỗi ñỉnh ta có:

Kí hiệu:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 74

D[i] : Chỉ số tại ñỉnh i (Tổng trọng số từ ñỉnh xuất phát tới ñỉnh i, ñược cập nhật

theo từng bước của thuật toán)

T[i] : Tên ñỉnh kề ngay trước ñỉnh i trên ñường ñi ngắn nhất ñược cập nhật theo

từng bước của thuật toán

Bước ðỉnh 5

ñược

chọn

Các ñỉnh

chưa xét

D[1],T[1] D[2],T[2] D[3],T[3] D[4],T[4]

Khởi tạo

1

2

3

4

5

4

2

3

1

1,3,4,2

1,3,2

1,3

1

12,5

12.5

12,5

12,5

12,5

7,4

7,4

7,4

7,4

9,5

9,5

9,5

9,5

9,5

4,5

4,5

4,5

4,5

4,5

Trong ñó, bước khởi tạo ñược cho trong dòng ñầu tiên.

Thực hiện bước 1, trong D[v], với v=1, 2, 3, 4 ở dòng ñầu tiên, thì D[4 ]

= 4 là nhỏ nhất nên ñỉnh 4 ñược chọn. Ta xác ñịnh lại các D[v] cho các ñỉnh còn lại

1, 2 và 3. Chỉ có D[2] là nhỏ ñi và D[2] = 7, vì D[4] + c(4,2) = 4 + 3 = 7 < ∞.

Tiếp tục thực hiện các bước 2, 3, 4 ta thu ñược ñộ dài ñường ñi ngắn nhất từ

ñỉnh 0 tới các ñỉnh 1, 2, 3, 4 ñược cho ở dòng cuối cùng trong bảng, chẳng hạn ñộ

dài ñường ñi ngắn nhất từ 5 tới 2 là D[2] = 7 và ñó là ñộ dài của ñường ñi 5�4�2.

Bài2 Tìm ñường ñi ngắn nhất từ 1 ñến các ñỉnh còn lại của ñồ thị

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 75

Kết quả tính toán theo thuật toán ñược trình bày theo bảng dưới ñây: Quy ước viết

hai thành phần của nhãn theo thứ tự d[v]. ðỉnh ñược ñánh dấu * là ñỉnh ñược chọn ñể

cố ñịnh nhãn ở bước lặp ñang xét, nhãn của nó không biến ñổi ở các bước tiếp theo, vì

thế ta ñánh dấu (-).

Bước lặp ðỉnh 1 ðỉnh 2 ðỉnh 3 ðỉnh 4 ðỉnh 5 ðỉnh 6

Khởi 0, 1 1, 1* ∞, 1 ∞, 1 ∞, 1 ∞, 1

1 - - 6, 2 3, 2* ∞, 1 8, 2

2 - - 4, 4* - 7, 4 8, 2

3 - - - 7, 4 5, 3*

4 - - - 6, 6* -

Bài 3 Nhà bác ñưa thư có việc bận, bác ñưa thư rất sốt ruột muốn về nhà ngay

nhưng bác phải ñưa một thư quan trọng cho anh B ở quận Ba ðình. Hiện tại bác ở

quận Thanh Xuân. ðường ñi từ chỗ bác tới nhà anh B phải ñi qua một số quận

huyện khác với khoảng cách giữa các quận như sau

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 76

Hãy giúp bác ñưa thư tìm ñường ñi ngắn nhất với thời gian ít nhất ñể bác có thể về

nhanh chóng giải quyết công việc gia ñình.

*Phân tích bài toán: Bác ñưa thư cần chuyển thư từ quận Thanh Xuân tới Quận Ba

ðình nhưng lại không có ñường ñi trực tiếp từ quận Thanh Xuân tới quận Ba ðình

mà phải ñi qua một số quận khác. Với ñiểm xuất phát là quận Thanh Xuân tìm các

con ñường có thể ñi tới quận Ba ðình và tính khoảng cách giữa hai quận ñó khi ñi

qua các con ñường khác nhau.

Ta tính khoảng cách từ Quận Thanh Xuân (Q.TX) tới các Q.Thanh Trì (Q.TT),

Q.Hoàng Mai (Q.HM), Q.Tây Hồ (Q.TH), Q.Hà ðông (Q.Hð). Ta thấy không có

ñường ñi trực tiếp từ Q.Thanh Xuân ñến Q.Hà ðông, nên còn 3 sự lựa chọn là ñi

qua Q.TT, Q.HM và Q.TH. Ta có khoảng cách tương ứng là:

Q.TX � Q.TT = 1km;

Q.TX � Q.HM = 7km;

Q.TX � Q.TH = 6km;

NX: Quãng ñường từ Q.TX ñến Q.TT ngắn nhất với 1km. Vậy ta sẽ chọn và ñánh

dấu lối ñi này.

Tiếp tục tính ñường ñi từ Q.TT ñến Q.HM, Q.TH, Q.H ð và Q.B ð. Ta có:

Q.TT � Q.HM = ∞;

Q.TT � Q.TH = 3km;

Q.TT � Q.Hð = 4km;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 77

Q.TT � Q.Bð = 1km;

NX: Quãng ñường từ Q.TT ñến Q.Bð là ngắn nhất 1km và là ñích của chuyến ñi.

Vậy tổng khoảng cách từ Q.TX � Q.Bð là 1+1=2km.

Giả sử các ñỉnh 1,2,3,4,5,6 tương ứng với các quận Thanh Xuân, Hoàng Mai, Tây

Hồ, Thanh Trì, Hà ðông và quận Ba ðình. Ta có ñồ thị sau:

Tìm ñường ñi ngắn nhất từ quận Thanh Xuân tới Ba ðình là tìm ñường ñi ngắn

nhất giữa từ ñỉnh 1 tới ñỉnh 6 của ñồ thị trên. Áp dụng thuật toán Dijkstra ta có bảng

sau:

1 2 3 4 5 6

Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞ 1,∞

1 ---- 1,7 1,6 1,1* ---- ----

2 ---- ---- 4,4 ---- 4,5 4,2*

3 ---- ---- ----* ---- 6,4 ----

4 ---- ---- ---- ---- ----* ----

Từ bảng trên ta thấy con ñường ngắn nhất ñể ñi từ ñỉnh 1 tới ñỉnh 6 là 1� 4 � 6

với trọng số là 2, nói cách khác bác ñưa thư có thể ñi từ quận Thanh Xuân tới quận

Thanh Trì và tới quận Ba ðình với quãng ñường là 2km.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 78

Bài 4 Một con hổ ñứng trên ñồi cao nhìn xuống khu rừng và phát hiện ra 5 con mồi

ở 5 vị trí khác nhau. Con hổ muốn bắt con Nai trong số 5 con vật ñó là Nai, Gà,

Hươu, Thỏ, Bò ñể ăn thịt. Khi con Hổ muốn bắt con Nai ñó, nó phải chạy qua

ñường mà 4 con vật còn lại ñang ñứng. Vị trí và khoảng cách mà các con vật ñược

biểu diễn như sau. Tìm ñường ñi ñể quãng ñường mà con Hổ phải chạy là ngắn nhất

ñể bắt ñược con Nai.

*Phân tích bài toán: Con hổ không thể bắt ñược tất cả 5 con vật ñó, và nó chỉ có thể

chọn 1. Trong các con ñường ñể ñi ñến chỗ con Nai mà nó muốn bắt ñó, có những

con ñường dài và ngắn khác nhau. Nó phải tính toán sao cho quãng ñường chạy ñến

con Nai ñó là ngắn nhất ñể ñề phòng con vật ñó nhìn thấy từ xa và bỏ chạy.

Gọi vị trí Hổ, Bò, Thỏ, Hươu, Nai tương ứng là 1,2,3,4 với các ñỉnh của ñồ thị sau:

ðể ñi từ 1 ñến 5 ta tính khoảng cách từ 1 ñến các ñỉnh còn lại:

1 � 2 = 4

1 � 3 = ∞

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 79

1 � 4 = ∞

1 � 5 = ∞

Ta thấy có ñường ñi duy nhất là 1�2.

Tiếp tục tính khoảng cách từ 2 � 3, 4, 5 ta có:

2 � 3 = 10

2 � 4 = 2

2 � 5 = 8

NX: Quãng ñường 2 � 4 là nhỏ nhất. ðánh dấu và chọn con ñường này.

Khi chọn ñường ñi, nếu ñường nào ñã ñược chọn và ñánh dấu sẽ không ñược xét lại

nữa. Vậy còn lại 2 ñỉnh chưa xét là 3 và 5, nhưng không có ñường ñi trực tiếp từ 4

� 3, chỉ còn ñường 4 � 5 với khoảng cách là 1km và là mục ñích của bài toán.

KL: ðường ñi ngắn nhất từ 1 � 5 là 1 � 2 �4 � 5 với khoảng cách là 1+4+2=7

Áp dụng thuật toán Djstral ta có bảng sau:

1 2 3 4 5

Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞

1 ---- 1,4* ---- ---- ----

2 ---- ---- 2,14 2,6* 2,12

3 ---- ---- ---- ---- 4,7*

4 ---- ---- ---- ---- ----

Nhìn vào bảng trên ta thấy ñường ñi ngắn nhất từ 1 ñến 5 là 1 - 2 - 4 - 5 với trọng số

là 7.

Nói cách khác con Hổ muốn bắt và ăn thịt con Nai thì Hổ phải ñi qua chỗ con Bò và

con Hươu.

Bài 5

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 80

Mèo Tom(1) rình chú chuột nhỏ Jeny(4) ñang ăn trộm phomat. Từ chỗ Tom ñến

Jeny có cái xô nước(2), chậu cây cảnh (3), ghế sofa(5) với thời gian ñể Tom chạy

ñến các ñồ vật trên và giữa các ñồ vật cũng như thời gian Tom chạy từ các ñồ vật

ñến Jeny như sau: xô nước chậu cây cảnh

Tom Jeny

ghế sofa

Tom có thể chạy ñến nấp ở chỗ các ñồ vật trên ñể rình và bắt Jeny. Tìm thời gian

nhỏ nhất ñể Tom chạy ñến bắt Jeny mà không bị Jeny phát hiện(nhờ nấp vào các ñồ

vật có trên ñường ñi)

Bài làm:

Giả sử vị trí các ñối tượng tương ứng với các ñỉnh 1, 2, 3, 4, 5 của ñồ thị sau:

Phân tích tương tự như 2 bài toán trên ta sẽ tìm ñược con ñường cần tìm

Áp dụng thuật toán Dijkstra ñể tìm ñường ñi ngắn nhất từ 1 � 4

1 2 3 4 5

Khởi tạo -1,0* 1,∞ 1,∞ 1,∞ 1,∞

1 ---- 1,3* ---- ---- 1,12

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 81

2 ---- ---- 2,8 ---- 2,7*

3 ---- ---- ---- 5,15* ----

4 ---- ---- ---- ---- ----

Dựa vào bảng trên ta có con ñường ngắn nhất là 1 – 2 – 5 - 4 với thời gian là 15

Bài 6 Cho ñồ thị có trọng số G = (X,E). Tìm ñường ñi ngắn nhất giữa 2 ñỉnh xp và

kết thúc của ñồ thị.

Phân tích bài toán :

Phương pháp 1: Tại mỗi ñỉnh thực hiện việc giảm trọng số nhiều lần.

Bài toán này cũng dùng mảng truoc ñánh dấu các ñỉnh trên ñường ñi như trên và

dùng cấu trúc hàng ñợi.

Có một ñiểm mới là nó cần thêm một mảng trongso: array[1…Nmax] of <type

trongso> (tuỳ vào bài toán <type trong so> có thể là kiểu real hoặc kiểu longint).

Trongso[i] bằng tổng trọng số của các cung nằm trên ñường ñi tính từ ñỉnh xp cho

ñến i. Bài toán của chúng ta trở thành tìm mảng trongso[i] sao cho nó ñạt giá trị

nhỏ nhất.

Thuật toán của phần này rất giống thuật toán duyệt chiều rộng nhưng cải tiền một

chút là có gắn thêm mảng trọng số.

Khi duyệt các ñỉnh kề của một ñỉnh u vừa lấy ra khỏi hành ñợi, gặp một ñỉnh i kề

với u ta không cần biết truoc[i] là ñỉnh nào, mà ta chỉ quan tâm ñường ñi từ u ñến i

có ngắn hơn ñường cũ không (trongso[i]???trongso [u] +a[u,i].

Trongso [i] chính là ñường ñi cũ ñến ñỉnh i, trongso [u] + a[u,i] là ñường ñi mới từ

ñỉnh u ñi ñến.

Nếu ñường mới ngắn hơn nghĩa là trongso[u] + a[u,i] <trongso [i] thì ta ghi nhận

ñường ñi mới, ta phải dán lại:

trongso [i] := trongso[u] + a[u,i];

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 82

truoc[i]:= u;

Thuật toán ñược trình bày cụ thể như sau:

Khởi tạo:

- Mảng trongso [i] = Maxlongint;

- Truoc [xp]: = -1;

- Khởi ñộng hàng ñợi và ñưa xp vào;

Thực hiện bước lặp.

REPEAT

- Lấy 1 ñỉnh khỏi hàng ñợi gắn vào biến u;

- Duyệt các ñỉnh i kề với u;

(Nếu ñường ñi mới ngắn hơn ñường ñi cũ thì thực hiện giảm trọng số cho i)

Nếu trongso[i]>trongso[u] +a[u,i] thì

+ trongso[i]:= trongso[u] + a[u,i];

+ truoc [i]:= u;

UNILT <hàng ñợi Q rỗng>;

Chương trình minh họa :

Program DIJSTRA_phuongphap1;

Const Nmax = 100;

Type MATRANKE = array[1…Nmax, 1…Nmax] of integer;

MANG = array [1…Nmax] of Longint;

Var a: MATRANKE;

q, duong, truoc, trongso: MANG;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 83

N, sold, xp, kt, qf, ql: Integer;

fifo: text:

(*fi: file input la tep doc du lieu vao

fo: file output la tep doc du lieu ra*)

Procedore Doctep;

Var i,j: integer;

Begin

Asign (fi,’matran:inp’); Reset(fi);

Readln (fi, N);

For i: = 1 to N do

For j: = 1 to N do

Read (fi, a[i,j]);

Readln (f,xp,kt);

Close (f);

End;

Procedure InitQ:

(*Thu tuc khoi dong hang doi *)

Begin

qf: = 0;

ql:= 1;

End;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 84

Procedure Put (u:integer);

(*Dua mot phan tu vao hang doi *)

Begin

Inc(ql);

q[ql]: = u;

End;

Function Get: Integer;

(*Ham lay mot phan tu ra khoi hang doi*)

Begin

Get:= q[qf];

inc [qf];

End;

Function Qempty: Boolean;

(*Ham kiem tra hang doi da rong hay chưa*)

Begin

Qempty:= (qf>ql);

End;

Procudure Dijstra

(*Thu tuc duyet Dijstra theo phuong phap 1: giam trong so nhieu lan*)

Var i, u: integer;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 85

Begin (*cac buoc khoi tao (giong trong phan thuat toan)*)

truoc[xp]:= -1;

Fullhar(…) = For i:= 0 to N do Trongso[i]:= MaxLongint;

Trongso[xp]:= 0;

InitQ;

Put(xp);

(*Bat dau vong lap*)

REPEAT

(*Lay mot dinh khoi hang doi gan vao bien u*)

u:= Get;

For i:= 1 to N do

(*Duyet tat ca cac dinh i cua do thi*)

If (a[u,i]>=0) and (trongso [i]>trongso [u] + a[u,i]then

(*Neu dinh i ke voi u va duong di cu lon hon duong di moi

thi:*)

Begin (*Gan lai gia tri duong di moi*)

trongso [i]:= trongso [u] +a[u,i];

(*danh dau duong di moi den i qua dinh truoc do la u*)

truoc [i]:= u;

Put(i);

End;

UNILTQempty: (*Ket thuc khi khong di duoc nua*)

End;

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 86

Procedure Timnguoc;

Var u:integer;

Begin

sold:= 0; (*Mảng ñường rỗng*)

(*Ban ñầu gán u bằng kt*)

u:= kt;

Repeat

(*Với mỗi bước lặp ghi u vào mảng duong*)

Inc(sold);

duong[sold]:= u;

(*Muốn ñến bước tiếp theo phải gắn u = truoc [u]*)

u:= truoc[u];

Unilt u = -1; (*Ket thuc khi u:= -1 do luc truoc ta gan truoc [xp]= -1).

End;

procedure Ghitep:

Var ij:integer;

Begin

Asign (fo, ‘kq.out’); Rewrite (fo);

If truoc [kt] <> 0 then

Begin Timnguoc;

For i:= sold downto 1 do

Write (fo, duong [i], ‘ ‘)’

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 87

End else

Writeln (f,0);

Close (fo);

End;

BEGIN

Doctep;

Dijstra;

Ghitep;

END.

Phương pháp 2: Giảm trọng số 1 lần tại mỗi ñỉnh.

ðể làm rõ thuật toán này ta xét ví dụ cụ thể sau:

G= (X,E) ñưa ra hình vẽ

Mảng ma trận trọng số như sau:

3

5

1 4

2 6

7

Ta tìm ñường ñi bắt ñầu từ ñỉnh 1.

-1 1 2 5 -1 -1 -1

1 -1 -1 3 -1 -1 -1

2 -1 -1 7 -1 -1 -1

5 3 7 -1 5 -1 13

-1 -1 -1 5 -1 2 -1

-1 -1 -1 -1 2 -1 6

-1 -1 -1 13 -1 6 -1

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 88

Các bước thực hiện của thuật toán ñối với ví dụ này như sau:

(M = MaxLongint). Trình tự thực hiện ở mỗi bước từ trái sang phải.

Bước

ðỉnh có

trọng số

nhỏ nhất

trong B

Tập A Tập B Mảng trongso Mảng Truoc

B1 [1] [2,3,4,5,6,7] [0,M,M,M,M,M,M] [-1,0,0,0,0,0,0,]

B2 [1] [2,3,4,5,6,7] [0,1,2,5,M,M,M] [-1,1,1,1,0]

B3 2 [1,2] [3,4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0]

B4 3 [1,2,3] [4,5,6,7] [0,1,2,4,M,M,M] [-1,1,1,2,0,0,0]

B5 4 [1,2,3,4] [5,6,7] [0,1,2,4,8,M,17] [-1,1,1,2,4,0,4]

B6 5 [1,2,3,4,5] [6,7] [0,1,2,4,8,10,17] [-1,1,1,2,4,5,4]

B7 6 [1,2,3,4,5,6] [7] [0,1,2,4,8,10,16] [-1,1,1,2,4,5,6]

B8 7 [1,2,3,4,5,6,7] [] nt Nt

B9 Kết thúc

Bài toán này cũng dùng mảng trước ñánh dấu các ñỉnh trên ñường ñi như trên

nhưng không dùng cấu trúc hàng ñợi.

Dùng một mảng trongso: array [1…Nmax] of <type trongso> (tuỳ vào bài toán

<type trongso> có thể là kiểu real hoặc kiểu longint).

Trongso [i] bằng tổng trọng số của các cung nằm trên ñường ñi từ ñỉnh xp cho ñến

i. Bài toán của chúng ta trở thành tìm mảng trongso [i] sao cho nó ñạt giá trị nhỏ

nhất.

Chia tập các ñỉnh của ñồ thị X thành 2 phần

a. Tập các ñỉnh có trọng số ñược gán cố ñịnh A.

b. Tập các ñỉnh có trọng số ñược gán tạm thời B.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 89

Trong suốt quá trình duyệt những ñỉnh ñược ñưa vào tập A thì trọng số của ñỉnh ñó

không thay ñổi và là ñộ dài ñường ñi ngắn nhất từ xp ñến nó, những ñỉnh ở tập B có

trọng số thay ñổi ñến khi nhỏ nhất thì ñược ñưa vào tập A. Cách thay ñổi trọng số

ñể nhỏ nhất ñược thể hiện như sau:

B1: Khởi tạo

Khởi tạo các giá trị của mảng trongso = Maxlongint (hoặc Maxreal)

Lập hai tập A và B. Ban ñầu A rỗng còn B = X

Duyệt tất cả các ñỉnh u kề với ñỉnh xp thì gán trongso [u] = a[u, xp] và truoc[u] =

xp;

REPEAT

B2: Tìm ñỉnh v thuộc tập B có trọng số nhỏ nhất.

ðưa ñỉnh v vào tập A (B/{v}; A + {v})

B3: Duyệt tất cả các ñỉnh i thuộc B mà kề với v

Nếu trongso[i]>trongso[v]+ a[i,v] thì

+ Gán lại trongso [i]:= trongso[v] + a[i,v];

+ ðồng thời gán truoc [i]:= v;

UNILT <B rỗng>;

Cấu trúc dữ liệu

Ma trận kề biểu diễn quan hệ của ñồ thị:

a(i;j) = -1 nếu i không nối với j

>= nếu i nối với j và a(a,j) là trọng số của cung 9i,j).

Mảng truoc và trongso ñược mô tả như trên.

Mảng duong ñể lưu các ñỉnh trên ñường ñi.

ðể biểu diễn tập A và B ta dùng kiểu tập hợp.

tap:set of <type tap>

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 90

Trong phần cài ñặt trên, khai báo tập A chỉ là minh hoà cho thuật toán còn trong bài

toán này không cần thiết phải sử dụng tập A, ta hiểu ngầm khi loại một phần tử khỏi

tập B thì nghĩa là ta ñã ñưa nó vào tập A.

Chương trình minh họa :

Program Difstra_Phuongphap2;

Const Nmax = 100;

Type Mang = array [0…Nmax] of Longint;

Tapcacdinh = set of a…Nmax;

Var a: array[1…Nmax, 1…Nmax] of integer;

duong, truoc, trongso: Mang;

N, sold, xp, kt: Integer;

tap A, tap B: set of Tapcacdinh;

(*Chỉ trình bày thủ tục Dijstra, các thủ tục khác tương tự như phần trên *)

Prcedure Dijstra;

Var i, u, v: integer;

Begin (*B1 khởi tạo các giá trị cần thiết *)

For i;= 0 to N do

Trongso [i]:= MaxLongint;

(*Khởi tạo tập B là tập tất cả các ñỉnh của ñồ thị*)

tapB: = [ ];

For i:= 1 to N do

tap B:= tapB +[i];

(*ðưa xp vào tập A*)

tapA:= [xp]

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 91

tapB: = tapB - [xp];

truoc[xp]:= -1;

(*Tìm các ñỉnh kề với xp gần trọng số và nhân cho những ñỉnh ñó*)

For i:= 1 to N do

if a [xp;i]>=0 then

Begin

trongso[i]:= a[xp,i];

truoc[i]:= xp

End;

REPEAT

(*Tìm ñỉnh v có trọng số nhỏ nhất trong tập B và ñưa vào tập A, loại khỏi tập

B*).

j: = Dinh_co_trong_so_min;

tapA:= tapA + [j];

tapB:= tapB + [j];

(*Tìm tất cả các ñỉnh thuộc B kề với ñỉnh v và thực hiện việc giảm trọng số

cho chúng*).

For i:= 1 to N do

If (i in tapB) and (a [i,j]>=0 and(trongso[i]>trongso[j] + a[i,j]) then

Begin

trongso [i]: = trongso[j] + a[i,j];

truoc[i]:= j;

End;

UNILT tapB = [ ];

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 92

End;

(*Hàm tìm ñỉnh có trọng số nhỏ nhất trong các ñỉnh thuộc tập B*)

Function Dinh_co_trong_so_min: Integer;

Var i,t: integer;

Begin tS [it]:= maxint

For i:= 1 to N do

If (i in tap B and (trongso[i] < trongso[t] then

t:=i;

Dinh_co_trong_so_+min:= t

End;

d. Bài tập tự giải

Bài tập 1: Áp dụng thuật toán Dijkstra tìm ñường ñi ngắn nhất cho ñồ thị sau:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 93

Bài tập 2: Di chuyển trên các hình tròn

Cho N hình tròn (ñánh số từ 1 ñến N). Một người muốn ñi từ hình tròn này

sang hình tròn khác cần tuân theo qui ước:

- Nếu khoảng cách giữa 2 ñiểm gần nhất của 2 hình tròn không quá 50 cm thì

có thể bước sang.

- Nếu khoảng cách này hơn 50cm và không quá 80cm thì có thể nhảy sang.

- Các trường hợp khác không thể sang ñược.

Một ñường ñi từ hình tròn này sang hình tròn khác ñuợc gọi là càng "tốt" nếu

số lần phải nhảy là càng ít. Hai ñường ñi có số lần nhảy bằng nhau thì ñường ñi nào

có số hình tròn ñi qua ít hơn thì ñường ñi ñó "tốt" hơn.

Các hình tròn ñược cho trong một file văn bản, trong ñó dòng thứ i mô tả

hình tròn số hiệu i (i = 1, 2,..., N) bao gồm 3 số thực: hoành ñộ tâm, tung ñộ tâm, ñộ

lớn bán kính (ñơn vị ño bằng mét).

Lập trình ñọc các hình tròn từ một file văn bản (tên file vào từ bàn phím), sau

ñó cứ mỗi lần ñọc số hiệu hình tròn xuất phát S và hình tròn kết thúc T từ bàn phím,

chương trình sẽ ñưa ra ñường ñi từ S ñến T là "tốt nhất" theo nghĩa ñã nêu (hoặc

thông báo là không có).

Yêu cầu ñường ñi ñược viết dưới dạng một dãy các số hiệu hình tròn lần lượt

cần ñược ñi qua trong ñó nói rõ tổng số các bước nhảy, tổng số các hình tròn ñi qua

và những bước nào cần phải nhảy.

Giới hạn số hình tròn không quá 100.

Bài tập 3: Tìm hành trình tốn ít xăng nhất

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 94

Trên một mạng lưới giao thông, một người muốn ñi từ ñiểm A ñến ñiểm B

bằng xe máy. Xe chứa ñược tối ña 3 lít xăng và chạy 100km hết 2,5 lít. Các trạm

xăng chỉ ñược ñặt ở các ñiểm dân cư, không ñặt ở giữa ñường và người này không

mang theo bất kỳ thùng chứa xăng nào khác. Hãy viết chương trình nhập vào mạng

lưới giao thông và xác ñịnh giúp người này tuyến ñường ñi từ A ñến B sao cho ít

tốn xăng nhất.

Bài tập 4: Di chuyển giữa các ñảo

Trên một ñảo quốc, có N hòn ñảo. Giả sử tất cả các ñảo ñều có hình dạng là

hình chữ nhật nằm ngang. Trên mỗi hòn ñảo có thể có sân bay nằm ở trung tâm ñảo,

có thể có cảng nằm ở 4 góc ñảo. Trên mỗi ñảo ñều có tuyến ñường xe buýt nối 4

góc ñảo với nhau và với trung tâm ñảo. Giữa 2 ñảo có thể ñi lại bằng máy bay nếu

cả 2 ñảo ñều có sân bay và có thể ñi lại bằng tàu nếu cả 2 ñảo ñều có cảng.

Giả sử rằng:

- Các tuyến ñường (bộ, không, thủy) ñều là ñường thẳng.

- Chi phí cho mỗi km và tốc ñộ của mỗi loại phương tiện là:

Phương tiện Tốc ñộ

(km/h)

Chi phí

(ñ/km)

Máy bay 1000 1000

Xe buýt 70 100

Tàu thủy 30 50

Hãy viết chương trình xác ñịnh tuyến ñường và cách di chuyển giữa 2 hòn

ñảo trong ñảo quốc sao cho:

- Thời gian di chuyển ít nhất.

- Chi phí di chuyển ít nhất.

- Thời gian di chuyển ít nhất nhưng với một số tiền chi phí không quá ð

ñồng.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 95

- Chi phí di chuyển ít nhất nhưng với thời gian di chuyển không vượt quá T

giờ.

Bài tập 5: Tìm ñường ngắn nhất

Giả sử X là tập các khu dân cư, U là tập các ñường sá nối liền các khu ñó. Ta

giả sử mọi chỗ giao nhau của các con ñường ñều thuộc X. Với con ñường u, số l(u)

là ñộ dài của u tính bằng km. Hãy chỉ ra tuyến ñường ñi từ một khu i sang khu j sao

cho tổng chiều dài là nhỏ nhất.

Bài tập 6: ðường ñi trên lưới

Cho 1 ma trận A[M, N], mỗi phần tử của nó chứa 1 số tự nhiên. Từ 1 ô (i, j)

ta có thể ñi sang ô kề nó (có chung 1 cạnh) nếu giá trị của ô kề này nhỏ hơn giá trị

lưu trong (i, j). Hãy tìm 1 ñường ñi từ ô (i, j) tới ô (k, l) trên ma trận sao cho phải ñi

qua ít ô nhất. Hãy tìm 1 ñường ñi từ ô (i, j) tới ô (k, l) trên ma trận sao cho tổng giá

trị các ô phải ñi qua nhỏ nhất.

Bài tập 7 : Tìm ñường với chi phí phải trả cho phép

Có N thành phố ñược ñánh số từ 1..N nối với nhau bằng các ñoạn ñường một

chiều. Mỗi ñoạn ñường bao gồm 2 thông số : ðộ dài và chi phí ñi của ñoạn ñường.

A sống tại thành phố 1 và A muốn di chuyển ñến thành phố N nhanh nhất có

thể.

Bạn hãy giúp A tìm ra ñường ñi ngắn nhất từ thành phố 1 ñến thành phố N

mà A có khả năng chi trả tiền.

Dữ liệu vào : ROADS.IN

- Dòng ñầu tiên chứa số nguyên K, 0 <= K <= 10000, số tiền mà A có.

- Dòng thứ 2 chứa số nguyên N, 2 <= N <= 100, số thành phố.

- Dòng thứ 3 chứa số nguyên R, 1 <= R <= 10000, tổng số ñoạn ñường.

- Mỗi dòng trong số R dòng tiếp theo mô tả một ñoạn ñường bằng các số S,

D, L và T cách nhau bởi ít nhất một khoảng trắng.

+ S là thành phố khởi hành, 1 <= S <= N.

+ D là thành phố ñến, 1 <= D <= N.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 96

+ L là ñộ dài của ñoạn ñường, 1 <= L <= 100.

+ T là lộ phí, 0 <= T <= 100.

Chú ý rằng giữa 2 thành phố có thể có nhiều ñoạn ñường nối 2 thành phố này.

Dữ liệu ra: ROADS.OUT

Chỉ có duy nhất 1 dòng chứa tổng ñộ dài của ñường ñi ngắn nhất từ 1->N và nhỏ

hơn K.

ROADS.IN

5

6

7

1 2 2 3

2 4 3 3

3 4 2 4

1 3 4 1

4 6 2 1

3 5 2 0

5 4 3 2

ROADS.OUT

11

ROADS.IN

0

4

4

1 4 5 2

1 2 1 0

2 3 1 1

3 4 1 0

ROADS.OUT

-1

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 97

Bài 12: Bài toán luồng cực ñại trong mạng Mục tiêu

- Trình bày ñược tư tưởng chủ ñạo của thuật toán Ford_Fulkerson và cài ñặt ñược

thuật toán.

- Phân tích ñược bài toán thực tế tương ứng phần lý thuyết ñã học.

- Sinh viên có khả năng tự học.

a. Nhắc lại lý thuyết

ðịnh nghĩa 1. Ta gọi mạng là ñồ thị có hướng G = (V,E), trong ñó có duy

nhất một ñỉnh s không có cung ñi vào gọi là ñiểm phát, duy nhất một ñỉnh t không

có cung ñi ra gọi là ñiểm thu và mỗi cung e = (v,w) ∈ E ñược gán với một số

không âm c(e) = c(v,w) gọi là khả năng thông qua của cung e.

ðịnh nghĩa 2. Giả sử cho mạng G = (V,E). Ta gọi luồng f trong mạng G =

(V,E) là ánh xạ f: E� R+ gán cho mỗi cung e =(v,w) ∈ E một số thực không âm

f(e) = f(v,w), gọi là luông trên cung e, thoả mãn các ñiều kiện sau:

1. Luồng trên mỗi cung e ∈ E không vượt quá khả năng thông qua của nó: 0

≤ f (e) ≤ c(e),

2. ðiều kiện cân bằng luồng trên mỗi ñỉnh của mạng : Tổng luồng trên các

cung ñi vào ñỉnh v bằng tổng luồng trên các cung ñi ra khỏi ñỉnh v, nếu v ≠ s,t:

0),()()()()(

=−= ∑∑+Γ∈−Γ∈ vwvw

f wvfvfvDiv

Trong ñó )(v−Γ - tập các ñỉnh của mạng mà từ ñó có cung ñến v, )(v+Γ - tập các

ñỉnh của mạng mà từ v có cung ñến nó:

{ } { }.),(:)(,),(:)( EwvVwvEvwVwv ∈∈=Γ∈∈=Γ +−

3.Giá trị của luồng f là số

.),(),()()()(

∑∑−Γ∈+Γ∈

==twsw

twfwsffval

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 98

Bài toán luồng cực ñại trong mạng Cho mạng G=(V,E). Hãy tìm luồng f* trong

mạng với giá trị luồng val(f*) là lớn nhất . Luồng như vậy ta sẽ gọi là luồng cực ñại

trong mạng.

Giải quyết bài toán

Từ mạng G = (V,E) khả năng thông qua các cung và các ñỉnh. Ta sẽ giải

quyết theo hai bước sau:

10 Xác ñịnh mạng G’.

20 Tìm luồng cực ñại trong mạng G’. Bắt ñầu từ luồng zero với khả năng

thông qua cung.

Thuật toán Ford – Fulkerson

1. Xuất phát từ một luồng chấp nhận ñược f.

2. Tìm một ñường ñi tăng luồng P. Nếu không có thì thuật toán kết thúc. Nếu

có, tiếp bước 3 dưới ñây.

3. Nếu δ(P) = +∞ thuật toán kết thúc.

Thuật toán gán nhãn (The labeling algorithm)

1. Nếu t ∈ VT hoặc VT = ∅, thuật toán kết thúc. Ngược lại thì chọn một ñỉnh u

∈ VT ñể thăm và ñưa nó ra khỏi VT. Xét tất cả các ñỉnh cạnh u, tức là xét mọi

cung có dạng (u,v) và (v,u).

2. Nếu (u,v) ∈ E, F(u,v) < C(u,v) và v chưa gán nhãn thì gán nhãn nó và ñưa v

vào tập VT.

3. Nếu (v,u) ∈ E, F(v,u) > 0 và v chưa gán nhãn thì gán nhãn nó và ñưa vào tập

VT.

b. ðề bài tập

Bài 1 Áp dụng thuật toán Ford-Fullkerson tìm luồng cực ñại bằng cách gán nhãn

cho luồng zero sau:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 99

c. Hướng dẫn giải

Bài 1

+ Bước lặp 1: s → a → b → t, δ1 = 1

+ Bước lặp 2: s → a → b → c → e → t, δ2 = 2

7,0

4,0

12,0 3,0

4,0 5,0

9,0

5,0 7,0

4,0

6,0

c

d e

t

b

s

a

c(s+,4)

7,0

4,0

12,0 3,0

4,0 5,0

9,0

5,0 7,0

4,0

6,0

d(s+,7) e(d+,4)

t(e+,2)

b(a+,6)

s

(s,∞)

a(s+,6)

7,4

4,4

12,0 3,0

4,0 5,0

9,0

5,0 7,0

4,0

6,4

c

d e

t

b

s

a

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 100

+ Bước lặp 3: s → c → e → t, δ3 = 1

+ Bước lặp 4: s → d → e → t, δ4 = 7

c(b+,2)

7,4

4,4

12,0 3,0

4,0 5,0

9,0

5,0 7,0

4,0

6,4

d(s+,7) e(c+,2)

t(e+,2)

b(a+,2)

s

(s,∞)

a(s+,2)

c

7,6

4,4

12,3 3,3

4,2 5,0

9,0

5,0 7,0

4,1

6,6

d e

t

b

s

a

c

7,6

4,4

12,2 3,2

4,2 5,0

9,0

5,0 7,0

4,0

6,6

d e

t

b

s

a

c(s+,4)

7,6

4,4

12,2 3,2

4,2 5,0

9,0

5,0 7,0

4,0

6,6

d(s+,7) e(c+,1)

t(e+,1)

b(a+,1)

s

(s,∞)

a(s+,0)

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 101

+ Bước lặp 5: s → c → d → e → t, δ5 = 2

+ Bước lặp 6: Không còn ñường tăng luồng nữa, Val(fmax) = 6+3+7 = 16.

d. Bài tập tự giải

Bài tập 1 : Cho G=(V,E) ñồ thị có hướng trong ñó không có cung (s,t). Chứng

minh rằng số ñường ñi cơ bản nối hai ñỉnh s và t là bằng số ít nhất các ñỉnh của ñồ

thị cần loại bỏ ñể trong ñồ thị không còn ñường ñi nối s với t.

c(s+,3)

7,6

4,4

12,3 3,3

4,2 5,0

9,0

5,0 7,0

4,1

6,6

d(s+,7) e(d+,7)

t(e+,7)

b(a+,1)

s

(s,∞)

a(s+,0)

c

7,6

4,4

12,10 3,3

4,2 5,0

9,7

5,0 7,7

4,1

6,6

d e

t

b

s

a

c(s+,3)

7,6

4,4

12,10 3,3

4,2 5,0

9,7

5,0 7,7

4,1

6,6

d(c+,3) e(d+,2)

t(e+,2)

b(a+,1)

s

(s,∞)

a(s+,0)

c

7,6

4,4

12,12 3,3

4,2 5,0

9,9

5,2 7,7

4,3

6,6

d e

t

b

s

a

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 102

Bài tập 2 : Xây dựng thuật toán tìm tập E1 tất cả các cung của ñồ thị mà việc tăng

khả năng thông qua của bất kỳ cung nào trong E ñều dẫn ñến tăng giá trị của luồng

cực ñại trong mạng.

Bài tập 3 : Cho hai dãy số nguyên dương {pi, i=1,2,…,m} và {qj, j=1,2,…,n}. Hãy

xây dựng ma trận A={aij : i=1,2,…,m; j=1,2,…n} với các phần tử

ai j ∈ {0,1} có tổng các phần tử trên dòng i là pi , tổng các phần tử trên cột j là qj.

Bài tập 4 : Có m chàng trai, n cô gái và k bà mối, mỗi bà mối p (p=1,2,…,k) có một

danh sách Lp một số chàng trai và cô gái trong số các chàng trai và cô gái nói trên là

khách hàng của bà ta. Bà mối p có thể se duyên cho bất cứ cặp trai gái nào là khách

hàng của bà ta, nhưng không ñủ sức tổ chức quá dp ñám cưới. Hãy xây dựng thuật

toán căn cứ vào danh sách Lp, dp, p=1,2,…,k; ñưa ra cách tổ chức nhiều nhất các

ñám cưới giữa m chàng trai và n cô gái với sự giúp ñỡ của các bà mối.

Bài tập 5 : Chuyển bi

Cậu bé vẽ N (N<=100) vòng tròn, ñánh số từ 1 tới N và tô màu các vòng tròn

ñó (có thể có các vòng tròn có màu giống nhau), sau ñó nối từng cặp các cung ñịnh

hướng, mỗi cung có một màu nhất ñịnh. Các màu (của cung và vòng tròn) ñược

ñánh số từ 1 ñến 100.

Cậu bé chọn 3 số nguyên khác nhau L, K và Q nằm trong phạm vi từ 1 tới N,

ñặt vào trong các vòng tròn số L và K mỗi vòng một hòn bi, sau ñó bắt ñầu di

chuyển bi theo nguyên tắc sau:

- Bi chỉ ñược chuyển theo cung có màu trùng với màu của vòng tròn chứa

viên bi thứ 2.

- Bi chỉ ñược chuyển theo chiều cung

- Hai viên bi không ñược ñồng thời ở cùng một vòng tròn;

- Không nhất thiết phải di chuyển lần lượt các viên bi,

- Quá trình di chuyển kết thúc, khi một trong hai viên bi tới vòng tròn Q.

Hãy lập trình xác ñịnh cách di chuyển ñể chấm dứt quá trình sau một số ít

nhất các bước chuyển.

Dữ liệu vào từ file BL.INP:

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 103

- Dòng ñầu: 4 số nguyên N L K Q

- Dòng thứ 2: N số nguyên C1, C2,…,Cn; Ci là màu vòng tròn i

- Dòng thứ 3: số nguyên M (0 < M < 10000)

- M dòng sau: mỗi dòng 3 số nguyên Ai Bi Di; xác ñịnh cung màu Di

từ vòng tròn Ai tới vòng tròn Bi.

Các số trên một dòng cách nhau một dấu cách.

Kết quả ñưa ra file BL.OUT:

- Dòng ñầu: CO hoặc KHONG, cho biết quá trình có kết thúc ñược

hay không,

- Nếu dòng ñầu là CO thì dòng 2 chứa số nguyên xác ñịnh số bước

chuyển tối thiểu .

BL.INP BL.OUT

5 3 4 1

2 3 2 1 4

8

2 1 2

4 1 5

4 5 2

4 5 2

5 1 3

3 2 2

2 3 4

5 3 1

3 5 1

CO

3

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 104

Bài tập 6 : Bảng ñiện

Một lưới ô vuông ñược phủ trên một bảng ñiện hình vuông. Vị trí nằm trên

giao của 2 ñường kề của lưới sẽ ñược gọi là nút. Tất cả có nxn nút trên lưới.

Có một số nút chứa tiếp ñiểm. Nhiệm vụ của bạn là cần nối các tiếp ñiểm với

các nút ở trên biên của bảng bởi các ñoạn dây dẫn (gọi là các mạch). Các mạch chỉ

ñược chạy dọc theo các ñường kẻ của lưới (nghĩa là không ñược chạy theo ñường

chéo). Hai mạch không ñược phép có ñiểm chung, vì vậy hai mạch bất kỳ không

ñược phép cùng chạy qua cùng một ñoạn ñường kẻ của lưới cũng như không ñược

chạy qua cùng một nút của lưới. Các mạch cũng không ñược chạy dọc theo các

ñoạn kẻ của lưới ở trên biên (mạch phải kết thúc khi nó gặp biên) và cũng không

ñược chạy qua nút chứa tiếp ñiểm khác.

Ví dụ: Bảng ñiện và các tiếp ñiểm ñược cho trong hình 2a. Nút tô ñậm trong

hình vẽ thể hiện vị trí các tiếp ñiểm.

Yêu cầu: Viết chương trình cho phép nối ñược một số nhiều nhất các tiếp

ñiểm với biên. Các tiếp ñiểm ở trên biên ñã thỏa mãn ñòi hỏi ñặt ra, vì thế không

nhất thiết phải thực hiện mạch nối chúng. Nếu như có nhiều lời giải thì chi cần ñưa

ra một trong số chúng.

Dữ liệu vào: file văn bản ELE.INP:

- Dòng ñầu tiên chứa số nguyên n (3 <= n <= 15).

- Mỗi dòng trong số n dòng tiếp theo chứa n ký tự phân cách nhau bởi

một dấu cách. Mỗi ký tự chỉ là 0 hoặc 1. Ký tự 1 thể hiện tiếp ñiểm,

ký tự 0 thể hiện nút không có tiếp ñiểm trên vị trí tương ứng của lưới.

Các nút ñược ñánh số từ 1 ñến n*n theo thứ tự từ trái sang phải, từ

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 105

trên xuống dưới. Chỉ số của nút chứa tiếp ñiểm sẽ là chỉ số của tiếp

ñiểm.

Kết quả: ghi ra file ELE.OUT:

- Dòng ñầu tiên chứa k là số tiếp ñiểm lớn nhất có thể nối với biên bởi

các mạch.

- Mỗi dòng trong số k dòng tiếp theo mô tả một mạch nối một trong

số k tiếp ñiểm với biên theo qui cách sau: ñầu tiên là chỉ số của tiếp

ñiểm ñược nối, tiếp ñến là dãy các ký tự mô tả hướng của mạch nối:

E: ñông, W: tây, N: bắc, S: nam. Giữa chỉ số và dãy ký tự phải có

ñúng một dấu cách, còn giữa các ký tự trong dãy ký tự không ñược có

dấu cách.

Kết quả phải ñược ñưa ra theo thứ tự tăng dần của chỉ số tiếp ñiểm.

Ví dụ:

ELE.IN ELE.OUT

6

0 0 0 1 1 1

0 0 0 0 1 0

0 0 0 1 1 1

0 0 0 0 0 0

0 0 1 1 1 1

0 0 0 1 0 1

11 E

16 NWN

17 SE

27 S

28 NWWSS

29 S

Bài tập 7: Một khóa học gồm N môn học, môn học i phải học trong ti ngày. Giữa

các môn học có mối quan hệ trước/sau: có môn học chỉ học ñược sau khi ñã học

một số môn học khác. Mối quan hệ ñó ñược thể hiện bởi một mảng hai chiều A[i, j];

i, j = 1, …, N trong ñó A[i, j] = 1/0 và A[i, i] bằng 0 với mọi i, A[i, j] = 1 khi và chỉ

khi môn học i phải ñược dạy xong trước khi học môn j (ngày kết thúc môn i phải

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 106

trứơc ngày bắt ñầu môn j). Môn học i phải dạy trước môn học j nếu có một dãy môn

học i1, i2, …, ik sao cho a[it, it+1] = 1, 1 <= t <= k-1, i1=i và ik=j. Nếu có một nhóm

các môn học từng ñôi một không có quan hệ trước/sau thì trong mỗi ngày, về

nguyên tắc, ta có thể học ñồng thời tất cả những môn học này (nếu không vi phạm

quan hệ với các môn học khác). Mảng A[i, j] ñược gọi là bế tắc nếu có một dãy các

môn học i1, i2,…, ik, k > 1, mà môn i1 phải dạy trước môn i2, môn i2 phải dạy trước

môn i3, …, môn ik-1 phải dạy trước môn ik, môn ik phải dạy trước môn i1.

Hãy viết chương trình làm các việc sau:

1. Hãy xét xem mảng A có bế tắc hay không.

2. Nếu mảng A không bế tắc, hãy tính xem khóa học có thể kết thúc trong

thời gian nhanh nhất là bao nhiêu ngày.

3. Theo các học bảo ñảm thời gian hoàn thành ngắn nhất ở câu 2, hãy tính

xem một học sinh trong quá trình học phải học ñồng thời trong một ngày

nhiều nhất bao nhiêu môn.

Dữ liệu vào ñược cho bởi file text có tên MH.DAT trong ñó số N ghi ở dòng

thứ nhất, trong nhóm N dòng tiếp theo, dòng thứ i ghi N số A[i, 1], …, A[i, N] dòng

cuối cùng ghi N số nguyên dượng ti không lớn hơn 30, 1 <= i <= N; N <= 30.

Kết quả ghi ra file TKB.DAT như sau: dòng thứ nhất ghi số 1/0 tùy theo

mảng A bế tắc / không bế tắc. Nếu dòng thứ nhất ghi số 0, ta mới ghi tiếp kết quả

câu 2 và 3.

Kết quả câu 2 ghi tiếp vào file TKB.DAT N+1 dòng như sau: dòng dầu ghi

số T là số ngày tối thiểu có thể hoàn thành khóa học, tiếp theo là N dòng trong ñó

dòng thứ i ghi 2 số X, Y với ý nghĩa môn học thứ i học từ ngày thứ X ñến ngày thứ

Y (chú ý rằng Y – X = ti – 1).

Kết quả câu 3 ghi tiếp vào file TKB.DAT như sau: dòng thứ nhất ghi 2 số Z,

W với ý nghĩa trong ngày Z phải học W môn (W là số nhiều nhất các môn học phải

học ñồng thời trong một ngày), tiếp theo là một dòng ghi tên các môn học phải học

ñồng thời trong ngày Z.

Trong các câu 2 và 3, có thể có nhiều lời giải tương ñương chỉ cần ñưa ra một lời

giải.

Ví dụ 1

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 107

MH.DAT TKB.DAT

4

0 1 0 0

0 0 1 0

0 0 0 1

1 0 0 0

1 1 1 1

1

Ví dụ 2

MH.DAT TKB.DAT

7

0 1 0 0 0 0 0

0 0 0 1 0 0 0

0 0 0 1 0 0 0

0 0 0 0 1 1 0

0 0 0 0 0 0 0

0 0 0 0 0 0 1

0 0 0 0 0 0 0

2 2 8 4 10 2 3

0

22

1 2

3 4

1 8

12

13 22

13 14

15 17

1 2

1 3

Bài tập 8: Giám ñốc một công ty quyết ñịnh tổ chức buổi tiệc trà gặp gỡ toàn thể

nhân viên trong công ty. Công ty ñựơc tổ chức theo mô hình phân cấp lãnh ñạo và

mối quan hệ thủ trưởng – nhân viên tạo thành cây có gốc là giám ñốc. ðể ñảm bảo

không khí tự nhiên, giám ñốc quyết ñịnh không ñể thủ trưởng và nhân viên dưới

quyền ngồi cùng một bàn. P gọi là thủ trưởng của Q, nếu P là thủ trưởng trực tiếp

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 108

của Q hoặc tồn tại dãy P1, P2, …, Pk (1 < k), sao cho P = P1, Q = Pk và Pi là thủ

trưởng trực tiếp của Pi+1 (i = 1, 2, … , k -1). Tất cả mọi người trong công ty ñược

ñánh số từ 1 ñến N (N là tổng số người trong công ty với giám ñốc bắt ñầu từ 1).

+ Yêu cầu: tính số lượng bàn ít nhất cần thiết ñể có thể bố trí cho mọi người ngồi

theo yêu cầu nêu trên và cho một phương án bố trí người ở mỗi bàn.

+ Dữ liệu vào: file text COMPANY.INP, dòng ñầu tiên là số nguyên m – số ghế tối

ña cho một bàn, dòng thứ 2 – số nguyên N – số người trong công ty, dòng thứ ba

(và các dòng sau nếu cần) là dãy số nguyên, các số cách nhau ít nhất một dấu cách

hoặc nhóm ký tự xuống dòng, số nguyên thứ i trong dãy cho biết ai là thủ trưởng

trực tiếp của nhân viên i. Giám ñốc không có thủ trưởng nên số này bằng 0. 2 <= m

<= 10, 1 <= N <= 200.

+ Kết quả: ñưa ra file text COMPANY.OUT, dòng ñầu tiên là số bàn ít nhất cần

thiết, các dòng sau mỗi dòng tương ứng với một bàn và chứa dãy số nguyên xác

ñịnh ai ñược bố trí ngồi sau bàn ñó.

Ví dụ:

COMPANY.INP

4

13

0 1 9 9 9 2 2 1 1 7 8 8 10

File kết quả COMPANY.OUT có thể có nội dung:

5

13 3 4 5

10 6 8

7 9 11 12

2

1

Bài tập 9: Trên bàn cờ NxN, hãy tìm cách sắp xếp số lượng tối ña các con hậu sao

cho không con nào có thể ăn con nào.

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 109

Bài tập 10: Cho 1 ñồ thị có hướng G, hãy tìm một tập hợp X0 ít nhất các ñỉnh của G

sao cho mọi ñỉnh i của G hoặc thuộc X0 hoặc i nối trực tiếp với ñịnh j thuộc X0.

Bài tập 11: Trên bàn cờ NxN, hãy tìm cách sắp xếp số lượng tối thiểu các con hậu

sao cho mọi ô cờ trên bàn cờ bị chiếu bởi ít nhất 1 con.

Bài tập 12: Một ký túc xá có 15 cô gái. Hàng ngày các cô ñi chơi với nhau theo bộ

3. Hỏi có thể ñưa các cô ñi chơi trong tối ña bao nhiêu ngày ñể không có 2 cô nào ñi

chung trong một bộ 3 quá 1 lần.

Hãy tổng quát hóa bài toán.

Bài tập 13: Một số hải cảng x1, x2, x3… có các mặt hàng mà các hải cảng y1, y2,

y3…cần ñến. Lượng hàng có ở xi là si và yêu cầu hàng hóa của yi là di. Nếu có tàu ñi

từ xi tới yj thì ta ký hiệu cij là tổng lượng hàng mà các tàu có thể vận chuyển từ xi tới

yj. Vậy có thể thỏa mãn mọi yêu cầu không? Tổ chức vận chuyển ra sao? Hãy viết

chương trình giải quyết bài toán trên.

Bài tập 14: Trong một cuộc du lịch, m gia ñình phân nhau ñi trên n xe. Các gia ñình

tương ứng có r1, r2, …, rm người và các xe tương ứng có s1, s2, …, sn chỗ ngồi. Hãy

tìm cách phân phối sao cho 2 người cùng gia ñình không ngồi chung một xe hoặc

cho biết không thể làm như vậy.

Bài tập15: Trong một trường trung học, mỗi học sinh nữ có m bạn nam và mỗi học

sinh nam có m bạn nữ. Hãy chỉ ra cách sắp xếp ñể mỗi cô gái có thể lần lượt khiêu

vũ với các bạn trai của mình và các chàng trai có thể lần lượt khiêu vũ với các bạn

gái của mình.

Bài 16: Một nhà in phải sản xuất n cuốn sách bằng 2 máy: một ñể in, một ñể ñóng

sách. Gọi ak là thời gian cần cho việc in cuốn thứ k và bk là thời gian cần cho việc

ñóng cuốn ñó. Tất nhiên là sách phải in xong mới ñóng, do ñó máy ñóng có thể phải

chờ ñợi lâu hay chóng. Vậy tiến hành theo thứ tự nào ñể có thể xong việc sớm nhất.

Bài tập 17: Ổn ñịnh

Trong một lớp có N dãy bàn và mỗi dãy có M chỗ ngồi. Trong lớp có K cán

sự lớp. Mỗi một cán sự cầm một ñề bài tập. Các cán sự này có nhiệm vụ chuyển ñề

bài tập ñến các học sinh khác ngồi kề mình ở phía trước, sau, trái và phải. Sau khi

các cán sự làm xong công việc của mình, mỗi học sinh thông báo số lượng ñề bài

Bài tập TOÁN RỜI RẠC 2 Bộ môn Công nghệ phần mềm - 2010

Trang 110

tập mình ñã nhận ñược. Dựa trên thông tin này hãy xác ñịnh vị trí của các cán sự

trong lớp.

Bài tập 18: Có một máy thu và một máy phát tín hiệu. Giả sử máy phát có thể phát

ñi 5 loại tín hiệu khác nhau a, b, c, d, e. Ở máy thu mỗi tín hiệu có thể ñược hiểu

theo 2 cách khác nhau: tín hiệu a có thể hiểu p hay q, tín hiệu b có thể hiểu q hay r,

... Số cực ñại các tín hiệu mà ta có thể sử dụng là bao nhiêu ñể cho ở máy thu không

xảy ra nhầm lẫn giữa các tín hiệu ñược sử dụng.