Tải bản đầy đủ (.doc) (27 trang)

(Sáng kiến kinh nghiệm) bài toán tìm cây khung trên đồ thị vô hướng

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

CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM
Độc lập - Tự do - Hạnh phúc

TÊN ĐỀ TÀI:

BÀI TỐN TÌM CÂY KHUNG TRÊN ĐỒ
THỊ VÔ HƯỚNG

Đồng Hới, tháng 01 năm 2019

1


CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM
Độc lập - Tự do - Hạnh phúc

TÊN ĐỀ TÀI:

BÀI TỐN TÌM CÂY KHUNG TRÊN ĐỒ
THỊ VÔ HƯỚNG

Họ và tên: Trần Lương Vương
Chức vụ: Tổ trưởng chuyên môn
Đơn vị công tác: Trường THPT Chuyên Võ Nguyên Giáp

Đồng Hới, tháng 01 năm 2019
2


1. PHẦN MỞ ĐẦU
1.1. Lý do chọn đề tài


Như ta đã biết, muốn giải một bài toán trong Tin học thì việc tìm ra ý tưởng giải
thuật là một điều bắt buộc phải làm, không kém quan trọng và đi kèm với việc đó là
phải biết lựa chọn cấu trúc dữ liệu phù hợp với ý tưởng giải thuật đó nhằm tối ưu hóa
bài tốn.
Chun đề về đồ thị là một trong những chuyên đề cơ bản khi giảng dạy cho học
sinh ở lớp chuyên Tin. Với rất nhiều bài tốn trên thực tế ta có thể mơ hình hóa, đưa về
cấu trúc trên đồ thị để giải quyết. Đồ thị có trọng số trên các cạnh có thể sử dụng để
giải các bài tốn như: Tìm đường đi ngắn nhất giữa hai thành phố trong một mạng lưới
giao thông; Lập lịch sửa chữa các tuyến đường sao cho vẫn đảm bảo lưu thông giữa
các khu dân cư, Lâp kế hoạch lắp đặt hệ thống điện sao cho tiết kiệm chi phí nhất ...
Để khai thác các tính chất của đồ thị trong việc giải quyết một số bài toán thực tế, thì
các bài tốn có thể giải dựa trên tính chất liên thơng của đồ thị là một lĩnh vực rất quan
trọng. Trong các bài tốn đó có bài tốn “Tìm cây khung của một đồ thị vơ hướng liên
thông” được lựa chọn và đưa vào giảng dạy cho khối lớp chuyên Tin của trường THPT
Chuyên Võ Nguyên Giáp.
Đó là lí do tơi chọn đề tài: “Bài tốn tìm cây khung trên đồ thị vô hướng” làm
đề tài nghiên cứu cho sáng kiến kinh nghiệm của mình.
1.2. Điểm mới của đề tài
“Bài tốn tìm cây khung trên đồ thị vô hướng” là một trong những chuyên đề
cơ bản và quan trọng khi bồi dưỡng học sinh giỏi Tin học trong nhà trường là
chuyên đề về lý thuyết đồ thị và các thuật tốn trên đồ thị. Có nhiều dạng đồ thị,
nhiều dạng bài toán và thuật toán trên đồ thị. Một bài toán tối ưu và nổi tiếng về đồ
thị là bài tốn tìm cây khung, cây khung cực tiểu.
Giải pháp được đặt ra là sử dụng thuật toán tìm cây khung, cây khung cực tiểu
để giải các bài tốn đặc trưng của nó đồng thời áp dụng thuật toán cho lớp bài toán
cơ bản nhất như kiểm tra tính liên thơng của đồ thị, đếm số thành phần liên thơng
của đồ thị. Khi sử dụng thuật tốn này để quay trở lại giải quyết các bài toán cơ
bản nói trên sẽ cho học sinh có định hướng tốt trong việc phân tích, lựa chọn thuật
tốn phù hợp, tốt nhất để thiết kế, cài đặt cho mỗi bài toán.


3


2. PHẦN NỘI DUNG
2.1. Thực trạng
Trong toán học và tin học, lý thuyết đồ thị nghiên cứu các tính chất của đồ thị.
Một cách khơng chính thức, đồ thị là một tập các đối tượng được gọi là các đỉnh (hoặc
nút) nối với nhau bởi các cạnh (hoặc cung). Cạnh có thể có hướng hoặc vơ hướng. Đồ
thị thường được vẽ dưới dạng một tập các điểm (các đỉnh nối với nhau bằng các đoạn
thẳng (các cạnh). Những ý tưởng cơ bản của đồ thị được đưa ra từ thế kỷ thứ XVIII
bởi nhà toán học Thụy Sĩ Leonhard Euler, ông đã dùng mô hình đồ thị để giải bài toán
về những cây cầu Konigsberg nổi tiếng.
Mặc dù lý thuyết đồ thị đã được khoa học phát triển từ rất lâu nhưng lại có
nhiều ứng dụng hiện đại. Đặc biệt trong khoảng vài mươi năm trở lại đây, cùng với sự
sự phát triển nhanh chóng của Cơng nghệ thơng tin, Lý thuyết đồ thị càng được quan
tâm nghiên cứu đến nhiều hơn. Hiện nay, môn học này là một trong những kiến thức
cơ sở của bộ môn khoa học máy tính. Đặc biệt là các thuật tốn trên đồ thị đã có nhiều
ứng dụng trong nhiều lĩnh vực khác nhau như: Mạng máy tính, Bưu chính viễn thơng,
Tối ưu hố, Giao thông vận tải, v.v...
Ở trường THPT Chuyên Võ Nguyên Giáp thì vấn đề bồi dưỡng học sinh giỏi,
bồi dưỡng giáo viên là một trong những vấn đề được quan tâm hàng đầu. Đặc biệt là
các lớp ở khối chuyên Tin thì u cầu học sinh khơng những phải nắm vững các kiến
thức về tư duy thuật tốn mà cịn phải biết sử dụng ngơn ngữ lập trình thành thạo và
các cấu trúc dữ liệu hợp lí để có thể giải được các bài toán trong Tin học.
Như ta đã biết: "Thuật tốn + Cấu trúc dữ liệu + Ngơn ngữ lập trình = Chương
trình". Như vậy, một trong những cơng việc khơng kém phần quan trọng để lập trình
giải một bài tốn trong Tin học đó là việc lựa chọn cấu trúc dữ liệu hợp lí. Do đó học
sinh cần phải biết cách khai thác và sử dụng cấu trúc dữ liệu một cách hợp lí. Từ việc
xác định được cấu trúc dữ liệu cần sử dụng, học sinh hình thành tư duy thuật tốn, lựa
chọn được thuật tốn tối ưu để giải quyết từng bài toán cụ thể.


4


2.2. Một số định nghĩa liên quan đến lý thuyết đồ thị
• Định nghĩa đơn đồ thị vơ hướng
Đơn đồ thị vô hướng G = (V, E) bao gồm V là tập các đỉnh, và E là tập các cặp
không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh.
1

2

3
5

4

Định nghĩa các đỉnh và cạnh của đồ thị vô hướng
Hai đỉnh u và v của đồ thị vô hướng G được gọi là kề nhau nếu (u, v) là cạnh
của đồ thị G. Nếu e=(u, v) là cạnh của đồ thị thì ta nói cạnh này liên thuộc với hai đỉnh
u và v, hoặc cũng nói là cạnh e là nối đỉnh u và đỉnh v, đồng thời các đỉnh u và v sẽ
được gọi là các đỉnh đầu của cạnh (u, v).
• Định nghĩa bậc của một đỉnh trong đồ thị vô hướng
Ta gọi bậc của đỉnh v trong đồ thị vô hướng là số cạnh liên thuộc với nó và sẽ
ký hiệu là deg(v).


6

1


2

3
5

4

• Định nghĩa đường đi trong đồ thị vơ hướng
Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n ngun dương, trên đồ thị vơ
hướng G = (V, E) là dãy x0, x1, x2, ..., xn-1, xn trong đó:
u = x0, v = xn, (xi, xi+1) € E, i = 0, 1, 2, 3 ... n-1
Đường đi nói trên cịn có thể biểu diễn dưới dạng dãy cạnh:
(x0, x1), (x1, x2), (x2, x3), ..., (xn-2, xn-1), (xn-1, xn)
Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi. Đường đi
được gọi là đơn nếu như khơng có cạnh nào bị lặp lại.
• Định nghĩa chu trình trong đồ thị vơ hướng
Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n ngun dương, trên đồ thị vơ
hướng G = (V, E) là dãy x0, x1, x2, ..., xn-1, xn trong đó:
u = x0, v = xn, (xi, xi+1) ∈ E , i = 0, 1, 2, 3 ... n-1.
5


Đỉnh u gọi là đỉnh đầu, còn đỉnh v gọi là đỉnh cuối của đường đi. Đường đi có
đỉnh đầu trùng với đỉnh cuối (tức là u = v) được gọi là chu trình. Chu trình được gọi là
đơn nếu như khơng có cạnh nào bị lặp lại.
• Định nghĩa liên thông trong đồ thị vô hướng
Đồ thị vô hướng G = (V, E) được gọi là liên thông nếu ln tìm được đường đi
giữa hai đỉnh bất kỳ của đồ thị.
• Định nghĩa thành phần liên thơng trong đồ thị vô hướng

Ta gọi đồ thị con của dồ thị G = (V, E) là đồ thị H = (W, F) trong đó:
W ⊆ V và F ⊆ E
Trong trường hợp đồ thị là khơng liên thơng, nó sẽ rã ra một số đồ thị con liên
thông đôi một không có đỉnh chung. Những đồ thị con liên thơng như vậy ta sẽ gọi là
các thành phần liên thông của đồ thị.
• Định nghĩa Cây trong đồ thị vơ hướng
Ta gọi cây T = (V, E) là đồ thị vô hướng liên thơng khơng có chu trình. Đồ thị
khơng có chu trình được gọi là rừng.
• Định nghĩa cây khung trong đồ thị vô hướng
Cho G = (V, E) là đồ thị vô hướng liên thông. Cây T = (V, F) với F ⊂ E được gọi
là cây khung của đồ thị.
2.3. Bài tốn tìm cây khung
2.3.1. Bài tốn thực tế
Xây cầu nối giữa các đảo
BRIDGE.???
Chủ đầu tư đang xây dựng một đặc khu kinh tế trên một quần đảo. Quần đảo có
n đảo được đánh số từ 1, 2, ... n. Trên các đảo đã được xây dựng xong cơ sở vật chất
hạ tầng phục vụ cho đời sống cũng như phát triển kinh tế. Tuy nhiên giữa các đảo chưa
được xây dựng chiếc cầu nào để nối giữa chúng nên việc đi lại giữa các đảo là rất vất
vả, đặc biệt là trong mua mưa bão. Để thu hút các nhà đầu tư đưa vốn phát triển đặc
khu, Chủ đầu tư quyết định lập dự án xây dựng những cây cầu nối giữa các đảo trong
đặc khu nhằm thúc đẩy sự phát triển kinh tế cũng như du lịch. Đơn vị thi cơng đã khảo
sát địa hình và cho Chủ đầu tư biết địa hình địa chất nơi đây đảm bảo có thể xây dựng
được một số cây cầu nối trực tiếp giữa các đảo, khi xây dựng xong đảm bảo người dân
giữa các đảo đi đến được với nhau bằng các cây cầu đã xây dựng.
Do không đủ nguồn vốn để xây dựng tất cả các cây cầu cùng một lúc, Chủ đầu
tư quyết định xây dựng một số cầu trong giai đoạn 1 sao cho đảm bảo người dân ở một
đảo có thể đến được các đảo còn lại bằng các chiếc cầu mới xây dựng.
Yêu cầu: Hãy giúp Chủ đầu tư lập kế hoạch xây dựng một số cầu ít nhất nhưng vẫn
đảm bảo người dân ở một đảo có thể đến được các đảo còn lại.

6


Dữ liệu vào: Cho trong file BRIDGE.INP có cấu trúc:
- Dòng 1: Ghi số nguyên dương n, là số lượng đảo trong đặc khu (2 ≤ n ≤ 100).
- Dòng thứ i trong n dòng tiếp theo: Mỗi dòng ghi n số 0 hoặc 1, số thứ j = 1 thể hiện
có thể xây được cầu nối trực tiếp giữa đảo i với đảo j (1 ≤ i, j ≤ n).
Dữ liệu ra: Ghi ra file văn bản BRIDGE.OUT theo cấu trúc:
- Dòng 1: Ghi số nguyên dương k, là số cầu cần phải xây dựng
- k dòng tiếp theo: Mỗi dòng ghi 2 số p, q thể hiện việc cần xây dựng cầu nối giữa đảo
p với đảo q. Hai số được ghi cách nhau một dấu cách.
Ví dụ:

BRIDGE.INP
6
0
1
0
1
1
1

1
0
1
1
0
0

0

1
0
0
0
0

1
1
0
0
1
0

1
0
0
1
0
0

1
0
0
0
0
0

BRIDGE.OUT
5
1

1
4
2
1

2
4
5
3
6

2.3.2. Đưa bài tốn về mơ hình đồ thị
Với bài tốn thực tế ở trên, ta có thể mơ hình hóa về đồ thị vô hướng như sau:
- Gọi mỗi đảo là một đỉnh của đồ thị.
- Gọi mỗi cây cầu nối trực tiếp giữa hai đảo là một cạnh của đồ thị.
Từ ví dụ cụ thể đã cho ở trên ta có đồ thị G = (V, E) sau đây:
6

1

2

3
5

4

Tập các đỉnh: V = {1, 2,3, 4,5, 6}
Tập các cạnh: E = {(1, 2);(1, 4);(1,5);(1, 6);(2,3); (2, 4);(4,5)}
2.3.3. Thuật toán

Việc xây dựng các cây cầu đảm bảo người dân có thể đi lại giữa các đảo với
nhau thực chất là đi tìm một đồ thị liên thơng. Để xây dựng ít cây cầu nhất nhưng vẫn
đảm bảo được người dân có thể đi lại giữa các đảo chính là đi xây dựng một cây
khung T = (V, F) với F ⊂ E .
7


Vậy thuật tốn để giải bài tốn này chính là thuật tốn tìm cây khung T = (V, F)
trên đồ thị G = (V, E), G là đồ thị liên thơng.
Có nhiều thuật tốn để giải quyết bài tốn tìm cây khung, nhưng ta chọn thuật
toán duyệt theo chiều sâu (DFS) hoặc duyệt theo chiều rộng (BFS).
Sau đây ta xây dựng thuật toán duyệt theo chiều sâu để giải quyết:
Thủ tục Solution dùng để tìm cây khung T:
Procedure Solution
Begin
T= ∅
While E ≠ ∅ do
Begin
- Lấy cạnh e = ( u , v ) trong tập cạnh E của đồ thị G.
- Dùng thủ tục BFS(u, v) để tìm đường đi từ u đến v trong
cây khung T = (V, F), nếu khơng tồn tại đường đi từ u đến v
thì: Nạp cạnh e = ( u, v ) vào cây khung T (nạp cạnh e vào
tập cạnh F của cây khung T).
- Loại bỏ cạnh e = ( u , v ) ra khỏi tập cạnh E của đồ thị G.
End;
End;
Hàm BFS(u, v) dùng để kiểm tra khi kết nạp thêm một cạnh e = ( u , v ) vào cây
khung T = (V, F) có tạo thành chu trình hay khơng.
Function BFS(u,v);
Begin

BFS := True;
Nạp u vào Stack, đánh dấu đã thăm u;
While Stack ≠ ∅ do
Begin
Lấy p từ đỉnh Stack;
For mỗi q là lân cận của p do
Begin
Nạp q vào Stack, đánh dấu đã thăm q;
End;
If p = v then
8


Begin
BFS:= False;
Exit;
End;
End;
End;
2.3.4. Chương trình
* Cấu trúc dữ liệu:
- Dùng hai mảng P, Q: Array[0..100] of Integer là danh sách kề chứa các cạnh
của đồ thị G, e = (Q[i], P[i]) là một cạnh của đồ thị.
- Dùng mảng B: array[1..100, 1..100] of Integer là ma trận kề để chứa các cạnh
của cây khung T tìm được.
- Dùng mảng Free: array[1..max] of Boolean để đánh dấu các đỉnh đã thăm
trong cây T để kiểm chu trình khi muốn nạp thêm một cạnh e = (Q[i], P[i]) vào cây
khung T.
- Dùng mảng Stack: array[1..max] of Integer để sử dụng thuật toán DFS trong
việc kiểm tra chu trình khi muốn nạp thêm một cạnh e = (Q[i], P[i]) vào cây khung T.

* Chương trình:
Program Thuat_toan_DFS_tim_cay_khung;
Const
Max = 1000;
fi='BRIDGE.INP';
fo='BRIDGE.OUT';
Type mmci=Array[0..Max] of Integer;
Var f:text;
P,Q:mmci;
B: array[1..Max, 1..Max] of Integer;
Free: array[1..Max] of Boolean;
Stack: array[1..Max] of Integer;
n, S, Last,Sl: Integer;
Procedure Init;
Begin
FillChar(P, SizeOf(P), 0);
FillChar(Q, SizeOf(Q), 0);
FillChar(B, SizeOf(B),0);
Sl:=0;
9


End;
Procedure Read_Data;
Var i,j,u: Integer;
Begin
Assign(f,fi);Reset(f);
Readln(f,N);
For i:=1 to n do
Begin

For j:=1 to n do
Begin
Read(f,u);
if (u<>0) and (iBegin
Sl:=Sl+1;
P[Sl]:=i;
Q[Sl]:=j;
End;
End;
Readln(f);
End;
Close(f);
End;
Procedure SPush(V: Integer);
Begin
Inc(Last);
Stack[Last] := V;
End;
Function SPop: Integer;
Begin
SPop := Stack[Last];
Dec(Last);
End;
Function DFS(u,v:Integer):Boolean;
Var i,j: Integer;
Begin
DFS:=True;
Fillchar(Free,Sizeof(Free),True);
FillChar(Stack, sizeof(Stack), 0);

10


Last := 0;
SPush(u); Free[u]:=False;
While Last > 0 do
Begin
i:=SPop;
For j:=1 to N do
if (B[i,j] = 1) And Free[j] then
Begin
SPush(j);
Free[j]:=False;
End;
if i = v then
Begin
DFS:= False;
Exit;
End;
End;
End;
Procedure Solution;
Var u,v,i:Integer;
Begin
For i:=1 to Sl do
Begin
u:=P[i];
v:=Q[i];
if DFS(u,v) then
Begin

B[u,v]:=1;
B[v,u]:=1;
End;
End;
End;
Procedure Write_Data;
Var i,j:Integer;
g:Text;
Begin
Assign(g,fo);
Rewrite(g);
11


Writeln(g,n-1);
Writeln(g, 6,' ', 7);
For i:= 1 to N do
For j := i+1 to N do
if B[i,j]=1 then
Writeln(g,i,' ',j);
Close(g);
End;
BEGIN
Init;
Read_Data;
Solution;
Write_Data;
END.
2.4. Bài toán tìm cây khung cực tiểu
Bài tốn cây khung nhỏ nhất của đồ thị là một trong số những bài toán tối ưu

trên đồ thị tìm được ứng dụng trong nhiều lĩnh vực khác nhau của đời sống. Trong
mục này ta sẽ tìm hiểu bài tốn thực tế, đưa bài tốn về mơ hình đồ thị, xây dựng và
lựa chọn thuật toán để giải quyết bài toán đặt ra.
Phát biểu bài toán tổng quát:
Cho G = (V, E) là đồ thị vô hướng liên thông với tập đỉnh V = {1, 2,3,..., n} và
tập các cạnh E gồm m cạnh. Mỗi cạnh e của đồ thị G được gán với một số thực c(e),
gọi là độ dài của nó. Giả sử T = (V, F) là cây khung của đồ thị G. Ta gọi độ dài c(T)
của cây khung T là tổng độ dài các cạnh của nó:

c(T ) = ∑ c(e)
e∈F

Bài toán đặt ra là trong số tất cả cây khung của đồ thị G hãy tìm cây khung với
dài nhỏ nhất. Cây khung như vậy được gọi là cây khung cực tiểu của đồ thị và bài toán
đặt ra là bài tốn tìm cây khung cực tiểu.

12


2.4.1. Bài tốn thực tế
Bài tốn Cắm trại
CAMP.???
Tỉnh đồn Q tổ chức cắm trại nhân dịp kỹ niệm ngày thành lập đồn 26-3. Theo
kế hoạch sẽ có n trại tham gia gồm một trại trung tâm của Ban tổ chức và trại của các
đơn vị, tất cả các trại được đánh số thứ tự từ 1, 2, ..., n. Ban tổ chức đã chọn được địa
điểm, khảo sát và lập bản đồ bố trí các trại, trong bản đồ có ghi rõ khoảng cách trực
tiếp giữa các trại để lắp đặt hệ thống dây điện. Khoảng cách giữa các trại được thể
hiện trong ma trận A kích thước n×n, trong đó A[i, j] là khoảng cách từ trại i đến trại j.
Vấn đề đặt ra là Ban tổ chức muốn lắp đặt hệ thống dây điện đảm bảo an toàn
và tiết kiệm chi phí nhất.

Yêu cầu: Hãy lập kế hoạch lắp đặt hệ thống dây điện từ trại trung tâm đến các trại sao
cho đảm bảo các trại đều có nguồn điện đến tận trại mình và tổng chiều dài dây điện
cần lắp đặt là nhỏ nhất.
Dữ liệu vào: Cho trong file CAMP.INP có cấu trúc:
- Dịng 1: Ghi số nguyên dương n, là số lượng trại tham gia (2 ≤ n ≤ 100).
- Dòng thứ i trong n dòng tiếp theo: Mỗi dòng ghi n số nguyên, số thứ j có giá trị là k
thể hiện giữa trại i với trại j có thể nối dây điện trực tiếp với nhau và độ dài dây nối là
k, nếu k = 0 tức là không thể nối dây điện trực tiếp giữa trị i với trại j (1 ≤ i, j ≤ n; 0 ≤
k ≤ 32000).
Dữ liệu ra: Ghi ra file văn bản CAMP.OUT theo cấu trúc:
- Dòng 1: Ghi số nguyên dương d, là tổng độ dài dây điện cần lắp đặt.
- d dòng tiếp theo: Mỗi dòng ghi 3 số p, q, k thể hiện việc cần nối dây điện trực tiếp
giữa trại p với trại q và độ dài dây nối là k. Các số được ghi cách nhau một dấu cách.
Ví dụ:

CAMP.INP
8
0 20 0 8 17
20 0 11 5 0
0 11 0 0 19
8 5 0 0 6
17 0 19 6 0
0 0 15 0 0
0 0 0 0 0
0 0 0 0 12
0 0 0 0 7

0
0
15

0
0
0
0
0
9

CAMP.OUT
0
0
0
0
0
12
0
0
0

0
0
0
0
0
7
9
0
0

61
1 4

2 3
2 4
3 6
4 5
6 8
7 8

8
11
5
15
6
7
9

13


2.4.2. Đưa bài tốn về mơ hình đồ thị
Với bài tốn thực tế ở trên, ta có thể mơ hình hóa về đồ thị vơ hướng như sau:
- Gọi mỗi trại là một đỉnh của đồ thị.
- Gọi mỗi đường nối dây điện trực tiếp giữa hai trại là một cạnh của đồ thị.
Từ ví dụ cụ thể đã cho ở trên ta có đồ thị G = (V, E) sau đây:
20
1

2

8


17

12

11
5
3

19
6

5

15
gg
g

7

9
6

7
8

4

Sau khi sử dụng thuật tốn Kruskal để tìm cây khung cực tiểu thì ta sẽ có cây khung:
1


2

8

11

7

5
3

6

5

15
gg
g

4

9
6

7
8

2.4.3. Thuật toán
Thuật toán Kruskal
Xây dựng tập cạnh F của cây khung cực tiểu T = (V, F) theo từng bước:

1. Sắp xếp các cạnh e ⊂ E của đồ thị G theo thứ tự tăng dần của c(e).
2. Bắt đầu từ tập F = ∅ , mỗi bước ta lấy trong tập E một cạnh theo thứ tự đã
được sắp xếp từ cạnh có độ dài nhỏ đến độ dài lớn hơn, để chọn ra một cạnh e mà việc
bổ sung cạnh e vào tập F không tạo thành chu trình.
3. Thuật tốn kết thúc khi ta tìm được tập F có đúng n - 1 cạnh, cụ thể:
Procedure Kruskal
Begin
F= ∅
While (E ≠ ∅ ) and ( F < n − 1 ) do
Begin
Chọn cạnh e ⊂ E là nhỏ nhất còn lại trong E;
14


E := E \{e} ;
If F ∪ {e} mà không tạo chu trình then

F := F ∪ {e} ;
End;
If ( F < n − 1 ) then Đồ thị G khơng liên thơng;
End;
2.4.4. Chương trình
*. Chương trình sử dụng thuật tốn DFS kiểm tra việc tạo thành chu trình:
Program CAMP_Kruskal_DFS;
Const
max = 1000;
fi='CAMP.INP';
fo='CAMP.OUT';
Type mmci=Array[0..max] of Integer;
Var

f:text;
P,Q,L:mmci;
B: array[1..max, 1..max] of Integer;
Free: array[1..max] of Boolean;
Stack: array[1..max] of Integer;
n, S, Last,Sl: Integer;
Procedure Init;
Begin
FillChar(P, SizeOf(P), 0);
FillChar(Q, SizeOf(Q), 0);
FillChar(B, SizeOf(B),0);
Sl:=0;
End;
Procedure Read_Data;
Var i,j,u: Integer;
Begin
Assign(f,fi);Reset(f);
Readln(f,N);
For i:=1 to n do
Begin
15


For j:=1 to n do
Begin
Read(f,u);
if (u<>0) and (iBegin
Sl:=Sl+1;
P[Sl]:=i;

Q[Sl]:=j;
L[Sl]:=u;
End;
End;
Readln(f);
End;
Close(f);
End;
Procedure Swap(Var x,y:Integer);
Var Tg:Integer;
Begin
Tg:=x;
x:=y;
y:=Tg;
End;
Procedure Sort;
Var i, j:Integer;
Begin
For i:=1 to Sl-1 do
For j:=i+1 to Sl do
if L[i] > L[j] then
Begin
Swap(L[i],L[j]);
Swap(P[i],P[j]);
Swap(Q[i],Q[j]);
End;
End;
Procedure SPush(V: Integer);
Begin
16



Inc(Last);
Stack[Last] := V;
End;
Function SPop: Integer;
Begin
SPop := Stack[Last];
Dec(Last);
End;
Function DFS(u,v:Integer):Boolean;
Var i,j: Integer;
Begin
DFS:=True;
Fillchar(Free,Sizeof(Free),True);
FillChar(Stack, sizeof(Stack), 0);
Last := 0;
SPush(u); Free[u]:=False;
While Last > 0 do
Begin
i:=SPop;
For j:=1 to N do
if (B[i,j] > 0) And Free[j] then
Begin
SPush(j);
Free[j]:=False;
End;
if i = v then
Begin
DFS:= False;

Exit;
End;
End;
End;
Procedure Solution;
Var u,v,i,Value:Integer;
Begin
17


For i:=1 to Sl do
Begin
u:=P[i];
v:=Q[i];
Value:=L[i];
if DFS(u,v) then
Begin
B[u,v]:=Value;
B[v,u]:=Value;
End;
End;
End;
Procedure Write_Data;
Var i,j,Sum:Integer;
g:Text;
Begin
Assign(g,fo);
Rewrite(g);
Sum:=0;
For i:= 1 to N do

For j := i+1 to N do
if B[i,j]>1 then
Sum:=Sum+B[i,j];
Writeln(g,Sum);
For i:= 1 to N do
For j := i+1 to N do
if B[i,j]>1 then
Writeln(g,i,' ',j,' ', B[i,j]);
Close(g);
End;
BEGIN
Init;
Read_Data;
Sort;
Solution;
Write_Data;
18


END.
*. Chương trình sử dụng phương pháp ghép cặp (Union) để kiểm tra việc tạo thành
chu trình:
Program CAMP_Kruskal_Union;
Const
max = 1000;
fi='CAMP.INP';
fo='CAMP.OUT';
Type mmci=Array[0..max] of Integer;
Var
f:text;

D,P,Q,L:mmci;
B: array[1..max, 1..max] of Integer;
n, S, Last,Sl: Integer;
Procedure Init;
Begin
FillChar(P, SizeOf(P), 0);
FillChar(Q, SizeOf(Q), 0);
FillChar(B, SizeOf(B),0);
FillChar(D, SizeOf(D),0);
Sl:=0;
End;
Procedure Read_Data;
Var
i,j,u: Integer;
Begin
Assign(f,fi);Reset(f);
Readln(f,N);
For i:=1 to n do
Begin
For j:=1 to n do
Begin
Read(f,u);
if (u<>0) and (iBegin
19


Sl:=Sl+1;
P[Sl]:=i;
Q[Sl]:=j;

L[Sl]:=u;
End;
End;
Readln(f);
End;
Close(f);
End;
Procedure Swap(Var x,y:Integer);
Var Tg:Integer;
Begin
Tg:=x;
x:=y;
y:=Tg;
End;
Procedure Sort;
Var i, j:Integer;
Begin
For i:=1 to Sl-1 do
For j:=i+1 to Sl do
if L[i] > L[j] then
Begin
Swap(L[i],L[j]);
Swap(P[i],P[j]);
Swap(Q[i],Q[j]);
End;
End;
Function Find(l:Integer):Integer;
Begin
While (l <> D[l]) do
l:= D[l];

Find:= l;
End;
Function Union(u,v:Integer):Boolean;
20


Var ntu,ntv:Integer;
Begin
Union:=False;
ntu:=Find(u);
ntv:=Find(v);
If ntu=ntv then exit;
If ntu>ntv then
D[ntv]:=ntu
Else
D[ntu]:=ntv;
Union:=True;
End;
Function Kruskal:Boolean;
Var i,slcanh,t:Longint;
Begin
For i:=1 to N do
D[i]:=i;
slcanh:=0;
t:=0;
While (slcanhBegin
inc(t);
If Union(P[t],Q[t]) then
Begin

B[P[t],Q[t]]:=L[t];
inc(slcanh);
End;
End;
If slcanh=N-1 then
Kruskal:= True
Else
Kruskal:=False;
End;
Procedure Write_Data;
Var i,j,Sum:Integer;
g:Text;
21


Begin
Assign(g,fo);
Rewrite(g);
Sum:=0;
For i:= 1 to N do
For j := i+1 to N do
if B[i,j]>0 then
Sum:=Sum+B[i,j];
Writeln(g,Sum);
For i:= 1 to N do
For j := i+1 to N do
if B[i,j]>0 then
Writeln(g,i,' ',j,' ', B[i,j]);
Close(g);
End;

BEGIN
Init;
Read_Data;
Sort;
If Kruskal then
Write_Data
Else
Begin
Assign(f,fo);
Rewrite(f);
Writeln(f,0);
Close(f);
End;
END.

22


3. KẾT LUẬN
3.1. Ý nghĩa, phạm vi áp dụng
Qua quá trình nghiên cứu và thực hiện, về cơ bản đề tài đã hoàn thành và đã đạt
được những kết quả sau:
- Tìm hiểu và trình bày về bài tốn tìm cây khung, cây khung cực tiểu;
- Tìm hiểu và trình bày về thuật tốn, giải bài tốn tìm cây khung, bài tốn tìm cây
khung cực tiểu;
- Trình bày được phương pháp tư duy phân tích bài tốn, đưa bài tốn thực tế về mơ
hình đồ thị để giải quyết;
- Viết được chương trình để giải các bài tốn thực tế đã trình bày trong đề tài.
Trong đề tài tơi đã trình bày nhiều thuật tốn tìm cây khung và cây khung cực
tiểu để học sinh có thể lựa chọn, phân tích độ phức tạp của mỗi thuật tốn. Từ đó hình

thành tư duy, kỹ năng giải quyết các vấn đề liên quan đến thuật toán đã được học.
Đề tài đã trình bày thuật tốn DFS để tìm cây khung, cây khung cực tiểu từ đó
học sinh tiếp cận và có thể nghiên cứu và sử dụng thuật toán tương tự là BFS để giải
quyết bài toán đặt ra. Qua đây học sinh ngoài việc nắm bắt được khả năng vận dụng
thuật toán cơ bản để giải quyết các lớp bài toán khác nhau mà một lần nữa học sinh
được củng cố, khắc sâu kiến thức đã được học.
“Bài tốn tìm cây khung trên đồ thị vô hướng” được áp dụng trong việc dạy
cho học sinh khối chuyên Tin, bồi dưỡng học sinh giỏi Tin học, tài liệu đọc thêm cho
các em học sinh u thích việc lập trình cũng như bộ môn Tin học. Đề tài được sử
dụng cho các giáo viên dạy Tin học tham khảo, nâng cao khả năng tư duy thuật tốn
cũng như khả năng lập trình của bản thân, từ đó nâng cao chất lượng dạy và học bộ
môn Tin học.
3.2. Những kiến nghị, đề xuất
Với thuật tốn Kruskal học sinh khơng chỉ sử dụng để tìm cây khung cực tiểu
mà cịn có thể vận dụng để giải lớp vấn đề liên quan đến kiểm tra tính liên thơng của
đồ thị, đếm số thành phần liên thơng của đồ thị ...
Có hai thuật tốn tốt, tối ưu để tìm cây khung cực tiểu đó là Kruskal và Prim.
Mỗi thuật tốn sử dụng một mơ hình tốn học khác nhau. Tuy nhiên, trong đề tài này
tôi chỉ trình bày thuật tốn tối ưu Kruskal cịn thuật tốn Prim là một hướng mới để
hướng dẫn học sinh tự nghiên cứu, tìm hiểu. Khi các học sinh tìm hiểu thuật tốn Prim
rồi thì từ đó các em có thể tự gđánh giá được điểm mạnh, điểm hạn chế của mỗi thuật
23


tốn để từ đó đúc rút được kinh nghiệm cho bản thân trong việc lựa chọn và thiết kế
thuật toán.
Rất mong nhận được các ý kiến đóng góp của quý thầy cơ và đồng nghiệp để đề
tài được hồn thiện hơn.
Xin chân thành cảm ơn!


24


MỤC LỤC
1. PHẦN MỞ ĐẦU.......................................................................................................3
1.1. Lý do chọn đề tài................................................................................................3
1.2. Điểm mới của đề tài............................................................................................3
2. PHẦN NỘI DUNG....................................................................................................4
2.1. Thực trạng...........................................................................................................4
.....................................................................................................................................4
2.2. Một số định nghĩa liên quan đến lý thuyết đồ thị............................................5
2.3. Bài tốn tìm cây khung......................................................................................6
2.3.1. Bài tốn thực tế.....................................................................................................................6
2.3.2. Đưa bài tốn về mơ hình đồ thị............................................................................................7
2.3.3. Thuật tốn.............................................................................................................................7
2.3.4. Chương trình........................................................................................................................9

2.4. Bài tốn tìm cây khung cực tiểu......................................................................12
2.4.1. Bài tốn thực tế...................................................................................................................13
2.4.2. Đưa bài tốn về mơ hình đồ thị..........................................................................................14
2.4.3. Thuật tốn...........................................................................................................................14
2.4.4. Chương trình......................................................................................................................15

3. KẾT LUẬN..............................................................................................................23

25


×