Upload
duonganh
View
218
Download
0
Embed Size (px)
Citation preview
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.1
CHƯƠNG III
CÂY
I. CÁC KHÁI NIỆM CƠ BẢN
1. Định nghĩa
Định nghĩa 3.1.1
Cây là đồ thị liên thông không chứa chu trình.
Ví dụ 3.1.1. Đồ thị sau là cây
v1
v2 v3
v4 v5 v6 v7 Hình 3.1.1
Gốc của cây là một đỉnh đặc biệt, thông thường là đỉnh trên cùng.
Mức của đỉnh là độ dài đường đi từ gốc đến đỉnh đó.
Độ cao của cây là mức lớn nhất của cây (tức mức của đỉnh cách xa gốc nhất).
Trong ví dụ trên nếu ta chọn v1 là gốc thì v2, v3 là những đỉnh mức 1, các
đỉnh v4, v5, v6, v7 có mức 2, và độ cao của cây là 2.
Định nghĩa 3.1.2
Cho T là cây có gốc v0. Giả sử x, y, z là các đỉnh của T và (v0, v1, ..., vn) là
đường đi từ v0 đến vn trong T. Khi đó ta gọi
vn1 là cha của vn
v0,...,vn1 là tiền bối của vn
vn là con của vn-1
y là hậu thế của x, nếu x là tiền bối của y
y và z là anh em nếu chúng đều là con của đỉnh x
x là đỉnh lá nếu nó không có con
x là đỉnh trong của cây nếu nó có con.
Định nghĩa 3.1.3
Rừng là đồ thị mà mỗi thành phần liên thông là cây.
Ví dụ 3.1.2. Đồ thị sau là rừng có 3 cây
Hình 3.1.2
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.2
2. Tính chất
Định lý 3.1.1 (định lý tương đương)
Cho T là đồ thị n đỉnh. Các mệnh đề sau tương đương
(i) T là cây.
(ii) T không chứa chu trình và có n1 cạnh.
(iii) T liên thông và có n1 cạnh.
(iv) T liên thông và mỗi cạnh là cầu.
(v) Hai đỉnh bất kỳ được nối với nhau bởi một đường đi duy nhất.
(vi) T không chứa chu trình và nếu thêm một cạnh nối hai đỉnh thì ta thu được
đúng 1 chu trình.
(vii) T liên thông và nếu thêm một cạnh nối hai đỉnh thì ta thu được đúng 1
chu trình.
Chứng minh
Các mệnh đề trên hiển nhiên tương đương với n=1.
(i)(ii): Quy nạp theo số đỉnh n. Giả sử đúng với mọi n k. Cho n=k+1.
Giả sử e là cạnh của T. Loại e khỏi T ta có đồ thị T’ gồm 2 thành phần liên thông
T1 và T2. Gọi ni , mi là số đỉnh và số cạnh tương ứng với Ti, i=1,2. Theo giả thiết
quy nạp
mi = ni 1, i =1,2
Vậy số cạnh của T là
1+ m1 + m2 = n1 + n2 1 = n 1
(ii)(iii): Bằng phản chứng. Giả sử T không liên thông và có k thành phần
liên thông (k 2) T1, T2, ..., Tk. Vì T không chứa chu trình nên các thành phần
liên thông cũng không chứa chu trình. Theo định nghĩa T1, T2, ..., Tk cũng là cây.
Gọi ni , mi là số đỉnh và số cạnh tương ứng với Ti, i=1,...,k. Theo (ii) ta có
mi = ni 1, i =1,...,k
Suy ra số cạnh m của T là
m = mi = (ni 1) = n k
mâu thuẫn với (ii) (m=n1).
(iii)(iv): Việc loại bỏ cạnh bất kỳ của T dẫn đến một đồ thị n đỉnh và n2
cạnh. Đồ thị này không thể liên thông được. Vậy mỗi cạnh của T là cầu.
(iv)(v): Do T liên thông nên hai đỉnh bất kỳ của nó được nối với nhau bằng
một dây đường đi. Nếu có cặp đỉnh được nối với nhau bằng 2 đường đi thì suy ra
đồ thị chứa chu trình và các cạnh trên chu trình đó không thể là cầu được, mâu
thuẫn.
(v)(vi): Hiển nhiên T không chứa chu trình. Bây giờ ta thêm cạnh e=(u,v).
Khi đó cạnh e cùng đường đi nối u và v tạo nên chu trình duy nhất của T.
(vi)(vii): Hiển nhiên.
(vii)(i): T liên thông. Nếu T có chu trình thì khi thêm cạnh nối hai đỉnh
trên chu trình ta sẽ nhận được 2 chu trình, vậy T là cây.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.3
Định lý 3.1.2. Tâm của cây là tập hợp hoặc chỉ có một đỉnh hoặc có hai đỉnh kề
nhau.
Chứng minh
Qui nạp theo số đỉnh n của cây.
Định lý hiển nhiên đúng với n = 1, 2, 3, 4.
Cho n > 4. Giả sử định lý đúng với mọi cây k đỉnh, k < n. Cho T là cây n
đỉnh. Ký hiệu T’ là cây nhận được từ T sau khi loại các đỉnh lá. Độ lệch tâm của
các đỉnh trong T’ giảm đi 1 đơn vị so với độ lệch tâm trong T. Vì vậy tâm của T’
cũng là tâm của T. Từ đó suy ra định lý.
3. Cây m-phân
Định nghĩa 3.1.4. Cây m-phân (m N*) là cây mà mọi đỉnh trong có tối đa m
con và có ít nhất một đỉnh có m con.
Cây m-phân đầy đủ là cây mà mọi đỉnh trong có đúng m con.
Cây cân bằng là cây mà mọi đỉnh lá có mức là h hay h1, trong đó h là chiều
cao của cây.
Ví dụ 3.1.3
(a) Cây tam phân (b) Cây tam phân (c) Cây nhị phân
không đầy đủ đầy đủ đầy đủ không cân bằng không cân bằng cân bằng
Hình 3.1.3
Định lý 3.1.3. Nếu cây m-phân đầy đủ có i đỉnh trong, thì nó có m.i+1 (=n)
đỉnh.
Chứng minh
Mỗi đỉnh trong có m đỉnh con suy ra cây có m.i đỉnh con. Thêm đỉnh gốc
không phải là đỉnh con của đỉnh khác ta có tất cả m.i + 1 đỉnh.
Hệ quả 3.1.4. Cho T là cây m-phân đầy đủ có i đỉnh trong, l đỉnh lá và n
đỉnh. Khi đó:
(i) l = (m 1).i + 1
(ii) 1
1
m
li &
1
1.
m
lmn
(iii) m
ni
1 &
m
nml
1)1(
Chứng minh. Suy ra trực tiếp từ định lý.
Định lý 3.1.5. Cho T là cây m-phân có l lá và chiều cao h. Khi đó
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.4
l mh
Nếu T là cây m-phân cân bằng đầy đủ thì
h = logml,
trong đó x (trần nguyên của x) ký hiệu số nguyên nhỏ nhất lớn hơn hoặc bằng x.
Chứng minh.
Bất đẳng thức có thể chứng minh dễ dàng bằng quy nạp theo h.
Từ định nghĩa cây m-phân đầy đủ cân bằng suy ra số lá l thoả
mh 1
< l mh
và từ đây suy ra đẳng thức.
Ví dụ 3.1.4. Xét trò chơi viết thư dây chuyền. Ban đầu có một người nhận được
một bức thư. Mỗi người khi nhận được thư hoặc sẽ viết thư cho 4 người chưa
nhận thư hoặc sẽ không viết thư cho ai cả. Hỏi có bao nhiêu người nhận được thư
(kể cả người đầu tiên), nếu không có ai nhận được nhiều hơn một bức thư và trò
chơi kết thúc khi có đúng 100 người nhận thư mà không viết tiếp cho người khác.
Giải
Trò chơi có thể biểu diễn bằng cây tứ phân đầy đủ. Các đỉnh tương ứng với
những người gửi thư cho người khác, còn lá là những người nhận thư mà không
viết tiếp. Vì vậy số lá là
l = 100
Như vậy số người nhận thư, tức số đỉnh,
1
1.
m
lmn =
14
1100.4
= 133
Số người viết thư, tức số đỉnh trong, là
i = n l = 133 100 = 33
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.5
II. CÂY PHỦ
1. Định nghĩa và các tính chất
Định nghĩa 3.2.1
Cho đồ thị G=(V,E). Cây T gọi là cây phủ hay cây bao trùm của G, nếu T là
đồ thị con phủ của G.
Ví dụ 3.2.1. Các cây T1 và T2 là cây phủ của đồ thị G
a b
c d
e f
g h
G T1 T2
Hình 3.2.1
Định lý 3.2.1
Đồ thị G=(V,E) có cây phủ khi và chỉ khi G liên thông.
Chứng minh.
(): Nếu G có cây phủ, thì hiển nhiên G liên thông.
(): Giả sử G là đồ thị liên thông. Nếu G không có chu trình thì theo định nghĩa
G là cây phủ của chính nó. Nếu G có chu trình thì ta bỏ 1 cạnh (không bỏ đỉnh)
trên chu trình đó. Đồ thị con thu được vẫn liên thông. Nếu vẫn còn chu trình ta
lại loại bớt 1 cạnh. Cứ tiếp tục quá trình trên cho đến khi không còn chu trình thì
ta thu được cây phủ của đồ thị G.
2. Các thuật toán tìm cây phủ
Thuật toán 3.2.1. Tìm theo chiều ngang
Trong thuật giải này ta ký hiệu Q là hàng đợi (queue) các đỉnh, Ke(x) là danh
sách các đỉnh kề x.
Đầu vào. Đồ thị G=(V,E).
Đầu ra. Cây phủ T hoặc kết luận đồ thị không liên thông.
Các bước.
(1) Khởi tạo:
Chọn đỉnh v1 bất kỳ. Khởi tạo hàng đợi Q := [v1], T là đồ thị gồm 1 đỉnh
v1 và không có cạnh, v1 là gốc.
(2) Thêm cạnh:
Rút đỉnh xQ. Duyệt các đỉnh y Ke(x), nếu y T thì thêm cạnh (x,y)
và đỉnh y vào T và đẩy y vào hàng đợi Q.
Nếu Q và T chưa phủ hết các đỉnh, thì quay lại bước (2), ngược lại
sang bước (3).
(3) Kết luận:
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.6
Nếu T phủ hết các đỉnh của đồ thị, thì T là cây phủ, ngược lại đồ thị không
liên thông.
Ví dụ 3.2.2. Xét đồ thị ở ví dụ trên
a b
c d
e f
g h
Hình 3.2.2
Ta xếp thứ tự các đỉnh là abcdefgh.
Khởi tạo: Q := [a]. T = ({a}, ). Chọn đỉnh a làm gốc.
Thêm cạnh:
Rút đỉnh a khỏi hàng đợi Q. Thêm các cạnh (a,b), (a,c), (a,g) và các đỉnh b,
c, g vào cây T.
T = ({a,b,c,g}, {(a,b), (a,c), (a,g)})
Đẩy các đỉnh b,c,g vào hàng đợi Q
Q = [b,c,g]
Thêm cạnh:
Rút đỉnh b khỏi hàng đợi Q. Thêm cạnh (b,d) và đỉnh d vào cây T.
T = ({a,b,c,g,d}, {(a,b), (a,c), (a,g), (b,d)})
Đẩy đỉnh d vào hàng đợi Q
Q = [c,g,d]
Thêm cạnh:
Rút đỉnh c khỏi hàng đợi Q. Thêm cạnh (c,e) và đỉnh e vào cây T.
T = ({a,b,c,g,d,e}, {(a,b), (a,c), (a,g), (b,d), (c,e)})
Đẩy đỉnh e vào hàng đợi Q
Q = [g,d,e]
Thêm cạnh:
Rút đỉnh g khỏi hàng đợi Q. Đỉnh a, e kề g đều đã nằm trong T. Vì vậy T vẫn
giữ nguyên
T = ({a,b,c,g,d,e}, {(a,b), (a,c), (a,g), (b,d), (c,e)})
và
Q = [d,e]
Thêm cạnh:
Rút đỉnh d khỏi hàng đợi Q. Thêm cạnh (d,f) và đỉnh f vào cây T.
T = ({a,b,c,g,d,e,f}, {(a,b), (a,c), (a,g), (b,d), (c,e), (d,f)})
Đẩy đỉnh f vào hàng đợi Q
Q = [e,f]
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.7
Thêm cạnh:
Rút đỉnh e khỏi hàng đợi Q. Đỉnh g, c, f kề e đều đã nằm trong T. Vì vậy T
vẫn giữ nguyên
T = ({a,b,c,g,d,e,f}, {(a,b), (a,c), (a,g), (b,d), (c,e), (d,f)})
và
Q = [f]
Thêm cạnh:
Rút đỉnh f khỏi hàng đợi Q. Thêm cạnh (f,h) và đỉnh h vào cây T.
T = ({a,b,c,g,d,e,f,h}, {(a,b), (a,c), (a,g), (b,d), (c,e), (d,f), (f,h)})
Đẩy đỉnh h vào hàng đợi Q
Q = [h]
Đến đây vì T đã phủ hết các đỉnh của đồ thị, quá trình tìm cây phủ kết thúc.
* Kết quả: Cây phủ T
T = ({a,b,c,g,d,e,f,h}, {(a,b), (a,c), (a,g), (b,d), (c,e), (d,f), (f,h)})
a b
c d
e f
g h Hình 3.2.3
Thuật toán 3.2.2. Tìm theo chiều sâu
Trong thuật giải này ta ký hiệu S là ngăn xếp (stack) các đỉnh, Ke(x) là danh
sách các đỉnh kề x.
Đầu vào. Đồ thị G=(V,E).
Đầu ra. Cây phủ T hoặc kết luận đồ thị không liên thông.
Các bước.
(1) Khởi tạo:
Chọn đỉnh v1 bất kỳ. Khởi tạo ngăn xếp S := [v1], T là đồ thị cây gồm 1
đỉnh v1 và không có cạnh, v1 là gốc của T.
(2) Thêm cạnh:
Xét đỉnh wS. Tìm đỉnh v Ke(w) thỏa v T.
Nếu tồn tại đỉnh v, thì
Thêm cạnh (w,v) và đỉnh v vào T và đẩy v vào ngăn xếp S.
Nếu T phủ hết các đỉnh, T là cây phủ, kết thúc;
Nếu S và T chưa phủ hết các đỉnh, thì quay lại bước (2).
Nếu không tồn tại đỉnh v Ke(w) thỏa v T thì đến bước (3).
(3) Kiểm tra điều kiện kết thúc:
Nếu w = v1, kết luận đồ thị không liên thông. Kết thúc.
Nếu w v1 sang bước (4)
(4) Quay lui:
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.8
Đẩy đỉnh w ra khỏi ngăn xếp S. Quay lại bước (2)
Ví dụ 3.2.3. Xét đồ thị ở ví dụ trên
a b
c d
e f
g h
Hình 3.2.4
Ta xếp thứ tự các đỉnh là abcdefgh.
Khởi tạo: v1:=a; S := [a]. T = ({a}, ). Chọn đỉnh a làm gốc.
Thêm cạnh:
Xét đỉnh w = a trên ngăn xếp S. Thêm cạnh (a,b) và đỉnh b vào cây T.
T = ({a,b}, {(a,b)})
Đẩy đỉnh b vào ngăn xếp S
S = [b,a]
Thêm cạnh:
Xét đỉnh w = b trên ngăn xếp S. Thêm cạnh (b,d) và đỉnh d vào cây T.
T = {{a,b,d}, {(a,b), (b,d)}}
Đẩy đỉnh d vào ngăn xếp S
S = [d,b,a]
Thêm cạnh:
Xét đỉnh w = d trên ngăn xếp S. Thêm cạnh (d,c) và đỉnh c vào cây T.
T = ({a,b,d,c}, {(a,b), (b,d), (d,c)})
Đẩy đỉnh c vào ngăn xếp S
S = [c,d,b,a]
Thêm cạnh:
Xét đỉnh w = c trên ngăn xếp S. Thêm cạnh (c,e) và đỉnh e vào cây T.
T = ({a,b,d,c,e}, {(a,b), (b,d), (d,c), (c,e)})
Đẩy đỉnh e vào ngăn xếp S
S = [e,c,d,b,a]
Thêm cạnh:
Xét đỉnh w = e trên ngăn xếp S. Thêm cạnh (e,f) và đỉnh f vào cây T.
T = ({a,b,d,c,e,f}, {(a,b), (b,d), (d,c), (c,e), (e,f)})
Đẩy đỉnh f vào ngăn xếp S
S = [f,e,c,d,b,a]
Thêm cạnh:
Xét đỉnh w = f trên ngăn xếp S. Thêm cạnh (f,h) và đỉnh h vào cây T.
T = ({a,b,d,c,e,f,h}, {(a,b), (b,d), (d,c), (c,e), (e,f), (f,h)})
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.9
Đẩy đỉnh h vào ngăn xếp S
S = [h,f,e,c,d,b,a]
Quay lui:
Đẩy đỉnh w = h ra khỏi ngăn xếp S,
S = [f,e,c,d,b,a]
Cây T không thay đổi
T = ({a,b,d,c,e,f,h}, {(a,b), (b,d), (d,c), (c,e), (e,f), (f,h)})
Quay lui:
Đẩy đỉnh w = f ra khỏi ngăn xếp S,
S = [e,c,d,b,a]
Cây T không thay đổi
T = ({a,b,d,c,e,f,h}, {(a,b), (b,d), (d,c), (c,e), (e,f), (f,h)})
Thêm cạnh:
Xét đỉnh w = e trên ngăn xếp S. Thêm cạnh (e,g) và đỉnh g vào cây T.
T = ({a,b,d,c,e,f,h,g}, {(a,b), (b,d), (d,c), (c,e), (e,f), (f,h), (e,g)})
Đẩy đỉnh g vào ngăn xếp S
S = [g,e,c,d,b,a]
Đến đây vì T đã phủ hết các đỉnh của đồ thị, quá trình tìm cây phủ kết thúc.
* Kết quả: Cây phủ T
T = ({a,b,d,c,e,f,h,g}, {(a,b), (b,d), (d,c), (c,e), (e,f), (f,h), (e,g)})
a b
c d
e f
g h Hình 3.2.5
Ghi chú. Trong các thuật toán tìm cây phủ, ta gọi thứ tự các đỉnh được đưa vào
cây T là thứ tự trước (preorder).
Trong thuật toán tìm cây phủ theo chiều sâu, sau khi kết thúc thuật toán, nếu
ngăn xếp S , ta lần lượt rút các đỉnh còn lại ra khỏi ngăn xếp S, thì thứ tự các
đỉnh bị loại khỏi ngăn xếp S gọi là thứ tự sau (postorder).
Trong ví dụ trên ta có thứ tự trước và thứ tự sau như sau
a b c d e f g h
thứ tự trước : 1 2 4 3 5 6 8 7
thứ tự sau : 8 7 5 6 4 2 3 1
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.10
3. Duyệt đồ thị vô hướng và tìm thành phần liên thông
Ta có thể sử dụng thuật toán tìm cây phủ để duyệt tất cả các đỉnh của đồ thị
và xác định thành phần liên thông của đồ thị như sau.
Trong thuật giải này ta ký hiệu tplt[i] là số hiệu thành phần liên thông của
đỉnh i, i=1,...,n.
Thuật toán 3.2.3. Duyệt đồ thị vô hướng
Đầu vào. Đồ thị G=(V,E), V={1, 2, ..., n}.
Đầu ra. Số thành phần liên thông K
Cây con Ti phủ thành phần liên thông thứ i, i =1,...,K
Các bước.
(1) for i:=1 to n do tplt[i]:=0; K:=0;
(2) for i:=1 to n do
if tplt[i] = 0 then
begin
K:= K+1;
<xuất phát từ đỉnh i thực hiện thuật toán tìm cây phủ TK,
trong đó mỗi đỉnh v thuộc cây TK được gán tplt[v]:=K>
end;
4. Đồ thị có hướng
4.1. Duyệt đồ thị có hướng
Cho đồ thị có hướng G=(V,E). Để duyệt đồ thị G ta thực hiện tương tự như
duyệt đồ thị vô hướng với thuật toán tìm cây phủ theo chiều sâu, trong đó danh
sách kề của mỗi đỉnh w, Ke(w), là các đỉnh cuối của các cung xuất phát từ w.
Điểm khác biệt ở đây là ta chưa thể xác định được thành phần liên thông mạnh
của đồ thị có hướng.
Trong thuật giải này ta sử dụng ký hiệu t[i] để nhận biết đỉnh i đã được duyệt
qua hay chưa, t[i] = 1 nghĩa là đã duyệt qua đỉnh i, i=1,...,n.
Thuật toán 3.2.4. Duyệt đồ thị có hướng theo chiều sâu
Đầu vào. Đồ thị G=(V,E), V={1,2, ..., n}.
Đầu ra. Thứ tự trước preord(i) và thứ tự sau postord(i) của đỉnh i,
i=1,...,n.
Các bước.
(1) for i:=1 to n do t[i]:=0; K:=0
(2) for i:=1 to n do
if t[i] = 0 then
begin
K:=K+1;
<xuất phát từ đỉnh i thực hiện thuật toán tìm cây phủ theo
chiều sâu TK, trong đó mỗi đỉnh v duyệt qua được gán
t[v] :=1, thứ tự trước preord(v) và thứ tự sau postord(v);
mỗi lần gán thứ tự các biến đếm tăng lên 1 đơn vị>
end;
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.11
Định lý 3.2.2. Đồ thị có hướng không có chu trình có hướng khi và chỉ khi
trong quá trình thực hiện thuật toán duyệt đồ thị có hướng theo chiều sâu danh
sách kề của các đỉnh đang xét không chứa đỉnh còn trong ngăn xếp.
Chứng minh
Giả thiết đồ thị không có chu trình có hướng. Ta giả thiết phản chứng rằng
trong quá trình thực hiện thuật toán duyệt đồ thị có hướng theo chiều sâu danh
sách kề của đỉnh w đang xét chứa đỉnh v còn trong ngăn xếp. Khi đó sẽ tồn tại
chu trình có hướng đi từ v qua các đỉnh trong ngăn xếp đến w và từ w quay về v
theo cung (w,v). Mâu thuẫn với giả thiết đồ thị không có chu trình có hướng.
Giả thiết đồ thị có chu trình có hướng sơ cấp C. Ký hiệu u1 là đỉnh đầu tiên
trong C được đưa vào ngăn xếp, và các đỉnh tiếp theo trên C là u2, u3, ..., uk. Theo
thuật toán, mỗi đỉnh trước khi bị đưa ra khỏi ngăn xếp, thì các đỉnh kề nó cũng đã
được duyệt. Vì vậy, ở thời điểm đỉnh u2 được đưa vào ngăn xếp, thì u1 vẫn còn
trong ngăn xếp. Truy hồi ta thấy, ở thời điểm đỉnh uk được đưa vào ngăn xếp, thì
u1 vẫn còn trong ngăn xếp. Khi đó danh sách kề đỉnh uk chứa đỉnh u1 đang còn
trong ngăn xếp.
Hệ quả 3.2.3. Cho đồ thị có hướng, không chu trình có hướng G=(V,E). Ký
hiệu postord(i) là thứ tự sau của i, i V, có được từ việc duyệt đồ thị theo
chiều sâu. Khi đó ta có
(i,j) E, postord(i) > postord(j)
4.2. Sắp xếp tô-pô Cho đồ thị có hướng n đỉnh, không có chu trình có hướng. Một cách đánh số
các đỉnh đồ thị sao cho mỗi cung đều đi từ đỉnh có số nhỏ hơn đến đỉnh có số lớn
hơn gọi là một sắp xếp tô-pô đồ thị.
Định nghĩa 3.2.2
Đồ thị ngược của đồ thị có hướng G=(V,E) là đồ thị G’=(V,E’), trong đó
E’ = {(i,j) | (j,i) E}
Từ hệ quả 3.2.3 suy ra
Định lý 3.2.4. Cho đồ thị có hướng n đỉnh, không có chu trình có hướng
G=(V,E). Ký hiệu postord(i) là thứ tự sau của i, i V, có được từ việc duyệt
đồ thị ngược của G theo chiều sâu. Khi đó postord(i) là một sắp xếp tô-pô của G.
Ta cũng có thể sắp xếp tô-pô theo phương pháp dựa trên định lý sau
Định lý 3.2.5. Mọi đồ thị có hướng, không có chu trình có hướng G có ít nhất
một đỉnh nguồn (không có cung vào) và một đỉnh đích (không có cung ra).
Chứng minh
Giả sử đồ thị G không có đỉnh đích. Xuất phát từ đỉnh bất kỳ, ta luồn tìm
được cung dẫn tới đỉnh khác. Vì số đỉnh hữu hạn nên đến lúc nào đó ta sẽ quay
lại đỉnh đã đi qua, và điều đó dẫn đến sự tồn tại chu trình có hướng. Vì vậy đồ thị
phải có đỉnh đích. Đồ thị ngược G’ của G cũng không có chu trình có hướng.
Vậy G’ phải có đỉnh đích, tức G phải có đỉnh nguồn.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.12
Thuật toán 3.2.5. Đánh số đỉnh nguồn
Đầu vào. Đồ thị có hướng, không có chu trình có hướng G=(V,E), V={1,2,
..., n}.
Đầu ra. Thứ tự sắp xếp tô-pô s[v], v V.
Các bước.
1. Khởi tạo: count := 0; H := G;
2. Nếu H = , kết thúc;
3. Chọn đỉnh nguồn v H (nửa bậc ra bằng 0);
Tăng count := count + 1;
s[v] := count;
H := H {v}
Quay lại 2.
4.3. Thành phần liên thông mạnh
Định nghĩa 3.2.3
Thành phần liên thông mạnh của đồ thị có hướng G là đồ thị con liên thông
mạnh tối đại của G.
Định lý 3.2.6. Mọi đồ thị có hướng G không liên thông mạnh được tạo thành từ
tập hợp các thành phần liên thông mạnh và tập hợp các cung nối các đỉnh của các
thành phần liên thông mạnh khác nhau.
Chứng minh
Xét đỉnh bất kỳ x G. Ký hiệu S là tập hợp các đồ thị con liên thông
mạnh chứa x. Hiễn nhiên {x} S và S có phần tử cực đại theo quan hệ bao
hàm. Phần tử cực đại này chính là thành phần liên thông mạnh chứa x.
Hai thành phần liên thông mạnh không có điểm chung, vì nếu có điểm
chung, chúng sẽ hợp nhất thành một thành phần liên thông mạnh.
Những cung không thuộc thành phần liên thông mạnh nào cả, hiển nhiên sẽ
liên thuộc các đỉnh trong các thành phần liên thông mạnh khác nhau.
Thuật toán 3.2.6 (Thuật toán Kosaraju). Tìm thành phần liên thông mạnh
Đầu vào. Đồ thị có hướng G=(V,E), V={1,2, ..., n}.
Đầu ra. Số thành phần liên thông mạnh K
Cây con Ti phủ thành phần liên thông mạnh thứ i, i=1,...,K
Các bước.
1. Duyệt đồ thị ngược của G theo chiều sâu. Gán nhãn thứ tự sau postord(v)
cho các đỉnh v V.
2. Thực hiện duyệt đồ thị G theo thứ tự giảm dần của thứ tự sau postord(v).
for i:=1 to n do tplt[i]:=0; K:=0;
for postord(u):=n downto 1 do
if tplt[u] = 0 then
begin
K := K+1;
<xuất phát từ đỉnh u thực hiện thuật toán tìm cây phủ TK,
trong đó mỗi đỉnh v thuộc cây TK được gán tplt[v]:=K>
end;
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.13
Ví dụ 3.2.4 Cho ®å thÞ cã híng G H×nh 3.2.6
§å thÞ ngîc G’ cña G lµ H×nh 3.2.7
DuyÖt ®å thÞ G’ theo chiÒu s©u ta nhËn ®îc rõng H×nh 3.2.8
vµ thø tù sau cho ë b¶ng sau Thø tù sau: 1 2 3 4 5 6 7 8 9 10 11 12 13 §Ønh : 9 8 7 6 5 4 3 1 2 11 12 13 10
DuyÖt ®å thÞ G theo thø tù gi¶m dÇn cña thø tù sau ta nhËn ®îc rõng
H×nh 3.2.9
1
2 3
4
6 5
7 8 9
10 11
12 13
1
2 3
4
6 5
7 8 9
10 11
12 13
1
3
4
5
6 7
8
9
2 10
13
11 12
10
11
13
12
2 1
6
5
4
3
7
8
9
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.14
víi mçi c©y lµ mét thµnh phÇn liªn th«ng m¹nh. Nh vËy ®å thÞ G cã 4 thµnh phÇn liªn th«ng m¹nh
< 10, 11, 13, 12 >; < 2 >; < 1, 6, 5, 4, 3, 7 >; < 8, 9 >
với mỗi cây là một thành phần liên thông mạnh. Như vậy đồ thị G có 4 thành
phần liên thông mạnh
< 10, 11, 13, 12 >; < 2 >; < 1, 6, 5, 4, 3, 7 >; < 8, 9 >
Định lý 3.2.7. Thuật toán Kosaraju tìm thành phần liên thông mạnh trong thời
gian và không gian tuyến tính.
Chứng minh
Phương pháp Kosaraju gồm hai bước thực hiện duyệt đồ thị theo chiều sâu,
vì vậy độ phức tạp là | V|2 đối với đồ thị không thưa và ( | V| + | E| ) đối vowis
đồ thị thưa (sử dụng danh sách kề).
Cho s và t là hai đỉnh trong cùng một cây được tạo ở bước 2. Ta chứng
minh rằng tồn tại đường đi có hướng từ s đến t và ngược lại.
Ký hiệu r là gốc của cây. Khi đó tồn tại đường đi có hướng từ r đến s trong
G, tức tồn tại đường đi có hướng từ s đến r trong đồ thị ngược G’. Điểm mấu
chốt của chứng minh là phải tồn tại đường đi từ r đến s trong đồ thị ngược G’. Vì
thứ tự sau (trong G’) của r lớn hơn thứ tự sau của s nên r sẽ được thăm trước tại
thời điểm cả hai đỉnh chưa được thăm, và khi s được thăm và đưa vào ngăn xếp
thì r vẫn còn trong ngăn xếp (vì nếu r không còn trong ngăn xếp thì thứ tự sau
của nó sẽ nhỏ hơn thứ tự sau của s). Suy ra tồn tại đường đi từ r đến s trong đồ thị
ngược G’, tức tồn tại đường đi có hướng từ s đến r trong G.
Tương tự tồn tại đường đi có hướng từ r đến t và từ t đến r trong G. Vậy tồn
tại đường đi có hướng từ s đến t và ngược lại.
Cho s và t là hai đỉnh liên thông mạnh hai chiều với nhau. Khi đó hiển
nhiên chúng nằm trong cùng một cây tạo ở bước 2, vì nếu một trong hai đỉnh
được thăm trước thì đỉnh còn lại cũng được thăm trước khi đỉnh gốc bị loại khỏi
ngăn xếp và kết thúc vòng lặp.
4.4. Định hướng mạnh của đồ thị
Cho đồ thị đơn vô hướng G = (V, E). Nếu mỗi cạnh của G được thay bằng
một cung và đồ thị có hướng G’ thu được liên thông mạnh thì G’ gọi là một định
hướng mạnh của G. Đồ thị G gọi là có thể định hướng mạnh nếu tồn tại một định
hướng mạnh của G.
Định lý 3.2.8 (Robbin). Đồ thị liên thông G là có thể định hướng mạnh khi và
chỉ khi nó không có cầu.
Chứng minh (xem [9]).
Thuật toán 3.2.7. Xây dựng định hướng mạnh.
Đầu vào. Đồ thị vô hướng G=(V,E) liên thông không cầu.
Đầu ra. Định hướng mạnh G’ của G.
Phương pháp.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.15
Giai đoạn 1. Tìm cây phủ T theo chiều sâu, trong đó các đỉnh được đánh số
thứ tự 1,2,...,n theo trình tự được chọn vào cây phủ.
Giai đoạn 2. Định hướng các cạnh.
Các cạnh (i,j) E, với i, j là các số thứ tự các đỉnh ở giai đoạn 1, được
định hướng theo quy tắc sau
- Nếu i < j và (i,j) T thì định hướng cung từ i đến j
- Nếu i < j và (i,j) T thì định hướng cung từ j đến i
Định lý 3.2.9 (Roberts). Thuật toán xây dựng định hướng mạnh là đúng.
Chứng minh (xem [9]).
Ví dụ 3.2.5. Tìm định hướng mạnh của đồ thị sau
Hình 3.2.10
Giải
Cây phủ T của đồ thị với các đỉnh gán số tìm theo chiều sâu như sau
8 1 4
3 5
7 2 6 Hình 3.2.11
Theo thuật toán, các cạnh trên cây T sẽ định hướng từ số bé đến số lớn, các
cạnh không thuộc cây T sẽ định hướng từ số lớn đến số bé. Cuối cùng ta có định
hướng mạnh sau
8 1 4
3 5
7 2 6 Hình 3.2.12
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.16
III. CÂY PHỦ NHỎ NHẤT
1. Phát biểu bài toán
Bài toán thực tế
Giả sử ta muốn xây dựng một hệ thống đường sắt nối n thành phố sao cho
giữa hai thành phố bất kỳ đều có thể thông thương với nhau. Nếu biết trước chi
phí xây dựng các tuyến đường thì bài toán đặt ra là phải xây dựng những tuyến
đường nào để tổng chi phí xây dựng là ít nhất.
Nếu ta coi các thành phố là đỉnh và các tuyến đường nối các thành phố là
cạnh kèm theo chi phí xây dựng thì ta có trọng đồ, ví dụ như trọng đồ ở Hình
3.3.1.
a 4 b
2 5
c 1 d
3 3 6
6 2 f
e Hình 3.3.1
Khi đó bài toán quy về tìm cây phủ bé nhất của đồ thị.
Bài toán tổng quát
Cho G=(V,E, (cij)) là trọng đồ liên thông có trọng số (cij). Tìm cây phủ T của
G có tổng trọng số
d(T) = Tji
ijc),(
là nhỏ nhất.
Định lý 3.3.1. (Điều kiện cần và đủ) Cho G=(V,E, (cij)) là đồ thị liên thông có
trọng số (cij). Khi đó T là cây phủ nhỏ nhất của G khi và chỉ khi mỗi cạnh e
G \ T có trọng số lớn nhất trên chu trình tạo bởi cạnh e và các cạnh của T.
Chứng minh
Điều kiện cần là hiển nhiên. Ta chứng minh điều kiện đủ.
Giả sử S là cây bất kỳ có k cạnh không thuộc T. Ta chứng minh
d(S) d(T)
qui nạp theo k.
Gọi e1, e2,...,en1 là các cạnh của T sắp theo thứ tự trọng số tăng dần
c(e1) c(e2) ... c(en1)
- Bước cơ sở: k=0. Hiển nhiên là d(S) = d(T) vì S=T.
- Bước qui nạp: Giả sử mọi cây với số cạnh không thuộc T ít hơn k đều có
trọng số không nhỏ hơn d(T).
Gọi ei là cạnh đầu tiên trong dãy các cạnh e1, e2,...,en1 của T không thuộc
S. Cạnh ei và các cạnh của S tạo thành chu trình duy nhất CS. Chu trình CS bắt
buộc phải chứa cạnh e S \ T (vì T không chứa chu trình).
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.17
Cạnh e cùng với các cạnh của T tạo thành chu trình duy nhất CT. Vì S chứa
các cạnh e1, ..., ei1 và e, nên CT phải có cạnh ej với j i và ej S (nếu
không, CT S, vô lý). Thay cạnh e bằng cạnh ei, ta thu được cây phủ S’ có d(S’)
d(S), vì c(e) c(ej) c(ei). Do S’ chỉ có k1 cạnh không thuộc T nên theo giả
thiết qui nạp
d(S) d(S’) d(T)
2. Thuật toán Prim tìm cây phủ nhỏ nhất
Thuật toán 3.3.1
Đầu vào. Đồ thị G=(V,E) có n đỉnh.
Trọng số của cạnh (i,j), (i,j)E, ký hiệu là cij.
Đầu ra. Cây phủ nhỏ nhất T, hoặc kết luận đồ thị không liên thông.
Các bước.
(1) Khởi tạo:
T là đồ thị gồm một đỉnh và không có cạnh.
(2) Kiểm tra điều kiện kết thúc:
Nếu T có n1 cạnh, kết thúc. Kết luận: T là cây phủ nhỏ nhất. Ngược lại
sang bước (3).
(3) Thêm cạnh:
Ký hiệu M là tập
M = { (i,j)E iT & j T }
Nếu M = , kết thúc. Kết luận đồ thị G không liên thông.
Ngược lại, tìm cạnh (k,h)M sao cho
ckh = min{cij (i,j)M}
Thêm cạnh (k,h) và đỉnh h vào T, sang bước (2).
Định lý 3.3.2. Thuật toán 3.3.1 là đúng.
Chứng minh
Cho cây phủ S bất kỳ của đồ thị G, ta phải chứng minh
d(S) d(T)
Ký hiệu các đỉnh và các cạnh lần lượt được thêm vào T là
v1, v2,...,vn và e1, e2,...,en1
trong đó ek =(vk,vk+1), k=1,2,...,n1.
Nếu các cạnh của T cũng là cạnh của S thì hiển nhiên d(S) = d(T).
Ngược lại gọi em là cạnh đầu tiên trong dãy các cạnh của T xây dựng theo
thuật toán không thuộc S. Cạnh em và các cạnh của S tạo thành chu trình duy
nhất C.
Chu trình C chứa đỉnh vmTm , trong đó Tm = {v1,...,vm} là số đỉnh có được
ở bước thêm cạnh em. Chu trình C bắt buộc phải chứa cạnh e nối đỉnh của Tm với
đỉnh không thuộc Tm (nếu không CT). Theo thuật toán thì cạnh e có trọng số
không nhỏ hơn trọng số của em. Vì vậy thay cạnh e bằng cạnh em, ta thu được cây
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.18
phủ S’ có d(S’) d(S). Lặp lại quá trình trên ta biến đổi cây S thành cây phủ T
và suy ra
d(S) d(S’) ... d(T)
Ví dụ 3.3.1. Tìm cây phủ nhỏ nhất của đồ thị
a 4 b
2 5
c 1 d
3 3 6
6 2 f
e Hình 3.3.2
(1) Khởi tạo: T chỉ có đỉnh a, không có cạnh:
T := ({a},), d(T) := 0
(2) Kiểm tra: Số cạnh của T là 0, sang bước (3)
(3) Thêm cạnh: Tập M là
M = {(a,b), (a,c), (a,e)}
Ta có
cac = 2 = min{cij | (i,j)M}
Thêm đỉnh c và cạnh (a,c) vào T,
T := ({a,c},{(a,c)}), d(T) := d(T) + cac = 2
(2) Kiểm tra: Số cạnh của T là 1, sang bước (3)
(3) Thêm cạnh: Tập M là
M = {(a,b),(a,e),(c,d),(c,e),(c,f)}
Ta có
ccd = 1 = min{cij | (i,j)M}
Thêm đỉnh d và cạnh (c,d) vào T,
T := ({a,c,d},{(a,c),(c,d)}), d(T) := d(T) + ccd = 3
(2) Kiểm tra: Số cạnh của T là 2, sang bước (3)
(3) Thêm cạnh: Tập M là
M = {(a,b),(a,e),(c,e),(c,f),(d,b),(d,f)}
Ta có
cae = ccf = 3 = min{cij | (i,j)M}
Thêm đỉnh e và cạnh (a,e) vào T,
T := ({a,c,d,e},{(a,c),(c,d),(a,e)}), d(T) := d(T) + cae = 6
(2) Kiểm tra: Số cạnh của T là 3, sang bước (3)
(3) Thêm cạnh: Tập M là
M = {(a,b),(c,f),(d,b),(d,f),(e,f)}
Ta có
cef = 2 = min{cij | (i,j)M}
Thêm đỉnh f và cạnh (e,f) vào T,
T := ({a,c,d,e,f},{(a,c),(c,d),(a,e),(e,f)}), d(T) := d(T) + cef = 8
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.19
(2) Kiểm tra: Số cạnh của T là 4, sang bước (3)
(3) Thêm cạnh: Tập M là
M = {(a,b),(d,b)}
Ta có
cab = 4 = min{cij | (i,j)M}
Thêm đỉnh b và cạnh (a,b) vào T,
T := ({a,c,d,e,f,b},{(a,c),(c,d),(a,e),(e,f),(a,b)}), d(T) := d(T) + cab = 12
(2) Kiểm tra: Số cạnh của T là 5, kết thúc.
Kết luận: Ta có cây phủ nhỏ nhất gồm các cạnh
(a,c),(c,d),(a,e),(e,f),(a,b)
a 4 b
2 5
c 1 d
3 3 6
6 2 f
e Hình 3.3.3
với tổng trọng số là d(T) = 2+1+3+2+4 = 12.
3. Thuật toán Kruskal tìm cây phủ nhỏ nhất
Thuật toán 3.3.2
Đầu vào. Đồ thị G=(V,E) có n đỉnh.
Trọng số của cạnh (i,j), (i,j)E, ký hiệu là cij
Đầu ra. Cây phủ nhỏ nhất T, hoặc kết luận đồ thị không liên thông.
Các bước.
1. Khởi tạo:
T := (V, ) là đồ thị gồm các đỉnh của G và không có cạnh.
2. Kiểm tra điều kiện kết thúc:
Nếu T có n1 cạnh, kết thúc và kết luận: T là cây phủ nhỏ nhất. Ngược lại
sang bước 3.
3. Thêm cạnh: Chọn cạnh có trọng số nhỏ nhất không thuộc T sao cho khi
thêm cạnh này vào T thì không tạo ra chu trình trong T. Quay lại bước 2.
Ngược lại, nếu không chọn được cạnh thêm vào T thì kết thúc. Kết luận
đồ thị G không liên thông.
Định lý 3.3.3. Thuật toán 3.3.2 là đúng.
Chứng minh
Cho e là cạnh bất kỳ không thuộc T. Cạnh e cùng các cạnh của T tạo thành
chu trình duy nhất C.
Với cạnh a bất kỳ trên C, ta phải có c(a) c(e). Thật vậy, ở bước (3) chọn a,
c(a) c(e), vì a là cạnh có trọng số nhỏ nhất mà khi thêm vào T không tạo thành
chu trình (lúc đó e và các cạnh của T cũng không tạo thành chu trình). Theo định
lý trên T là cây phủ nhỏ nhất.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.20
Ví dụ 3.3.2. Tìm cây phủ nhỏ nhất của đồ thị
a 4 b
2 5
c 1 d
3 3 6
6 2 f
e Hình 3.3.4
1. Khởi tạo: T := ({a,b,c,d,e,f}, ), không có cạnh, số cạnh e:=0, trọng số
d(T):=0.
2. Kiểm tra: Số cạnh của T e=0, sang bước 3.
3. Thêm cạnh: Trong các cạnh không thuộc T cạnh (c,d) có độ dài nhỏ nhất là
1.
Thêm cạnh (c,d) vào T. Ta có
T = ({a,b,c,d,e,f }, {(c,d)}) , d(T):=d(T)+1=1 và số cạnh e=1
2. Kiểm tra: Số cạnh của T là 1, sang bước 3.
3. Thêm cạnh: Trong các cạnh không thuộc T cạnh (a,c) có độ dài nhỏ nhất là
2 và không cùng các cạnh của T tạo thành chu trình.
Thêm cạnh (a,c) vào T. Ta có
T = ({a,b,c,d,e,f }, {(c,d),(a,c)}) , d(T):=d(T)+2=3 và số cạnh e=2
2. Kiểm tra: Số cạnh của T là 2, sang bước 3.
3. Thêm cạnh: Trong các cạnh không thuộc T cạnh (e,f) có độ dài nhỏ nhất là
2 và không cùng các cạnh của T tạo thành chu trình.
Thêm cạnh (e,f) vào T. Ta có
T = ({abcdef}, {(c,d),(a,c),(e,f)}) , d(T):=d(T)+2=5 và số cạnh e=3
2. Kiểm tra: Số cạnh của T là 3, sang bước 3.
3. Thêm cạnh: Trong các cạnh không thuộc T cạnh (a,e) có độ dài nhỏ nhất là
3 và không cùng các cạnh của T tạo thành chu trình.
Thêm cạnh (a,e) vào T. Ta có
T = ({abcdef}, {(c,d),(a,c),(e,f),(a,e)}) , d(T):=d(T)+3=8 và số cạnh e=4
2. Kiểm tra: Số cạnh của T là 4, sang bước 3.
3. Thêm cạnh: Trong các cạnh không thuộc T cạnh (a,b) có độ dài nhỏ nhất là
4 và không cùng các cạnh của T tạo thành chu trình.
Thêm cạnh (a,b) vào T. Ta có
T = ({abcdef}, {(c,d),(a,c),(e,f),(a,e),(a,b)})
d(T):=d(T)+4=12 và số cạnh e=5
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.21
2. Kiểm tra: Số cạnh của T là 5, Kết thúc.
Kết luận: Ta có cây phủ nhỏ nhất gồm các cạnh
(c,d),(a,c),(e,f),(a,e),(a,b)
a 4 b
2 5
c 1 d
3 3 6
6 2 f
e Hình 3.3.5
với tổng trọng số là d(T) = 12.
4. Ứng dụng
4.1. Bài toán cây phủ lớn nhất
Cho G = (V,E, (cij)) là đồ thị liên thông có trọng số (cij). Tìm cây phủ T của
G có tổng trọng số
d(T) = Tji
ijc),(
là lớn nhất.
Xét trọng đồ G’ = (V,E, (cij)). áp dụng các thuật toán tìm cây phủ nhỏ nhất
Prim hoặc Kruskal (vì chúng không phụ thuộc dấu của trọng số) ta tìm cây phủ
nhỏ nhất T* của đồ thị G’ thỏa
Tji
ijc),(
*),( Tji
ijc cây phủ T của đồ thị G’
*),( Tji
ijc Tji
ijc),(
cây phủ T của đồ thị G
Như vậy cây T* cũng là cây phủ lớn nhất của đồ thị G.
4.2. Bài toán tìm mạng điện với độ tin cậy lớn nhất
Cho lưới điện có n nút. Đường dây nối nút i với nút j có độ tin cậy pij. Hãy
tìm cây phủ T với độ tin cậy toàn phần
p(T) = Tji
ijp),(
là lớn nhất.
Bài toán này dẫn về bài toán tìm cây phủ nhỏ nhất với trọng số mỗi cạnh (i,j)
là
cij = log2pij
Thực vậy, cho T là cây phủ nhỏ nhất và T’ là cây phủ bất kỳ. Ta có
T
ijpj)(i,
2 )log(
'j)(i,
2 )log(T
ijp
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.22
T
ijpj)(i,
2log 'j)(i,
2logT
ijp
Tji
ijp),(
2log
'),(
2logTji
ijp
Tji
ijp),(
'),( Tji
ijp
p(T) p(T’)
Vậy T là cây phủ có độ tin cậy toàn phần lớn nhất.
4.3. Bài toán Steiner trên đồ thị
Trong các mục trước ta xét bài toán tìm cây phủ nhỏ nhất của đồ thị
G=(V,E,c) mà các cạnh của cây bao trùm toàn bộ các đỉnh của đồ thị G. Bây giờ
ta xét bài toán tổng quát hơn, gọi là bài toán Steiner trên đồ thị:
Cho đồ thị G=(V,E) có trọng số và tập W V. Tìm cây T =(W’, F) trong G
nhỏ nhất bao trùm tất cả các đỉnh của W. Cây T gọi là Cây Steiner của W, và
W’W gọi là các điểm Steiner của W ứng với cây T.
Ghi chú. Nếu V là tập tất cả các điểm trên mặt phẳng và trọng số của cạnh nối
2 đỉnh là khoảng cách giữa 2 điểm đó (đồ thị vô hạn), thì bài toán Steiner gọi là
bài toán Steiner với độ dài Euclide :
Trên mặt phẳng cho tập các điểm P, nối chúng bằng các đoạn thẳng sao cho
tổng các đoạn thẳng là nhỏ nhất.
Sau đây là lời giải cho trường hợp P có 3 và 4 điểm
a
b
a
v b u v
1200 120
0 120
0
c c d
(a) (b) Hình 3.3.6
Trường hợp nối 3 điểm a,b,c ta tìm điểm v sao cho các góc avb = avc =
bvc = 1200 (Hình 3.3.6.a).
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.23
Trường hợp nối 4 điểm a,b,c,d ta tìm điểm u,v sao cho các góc auv =
cuv = bvu = dvu = 1200 (Hình 3.3.6.b).
Ghi chú. Nếu W là tập con thực sự của V, thì cây phủ nhỏ nhất của đồ thị <W>
sinh bởi W có thể không phải là cây Steiner của W.
Ví dụ 3.3.3. Xét đồ thị sau
6
7 3 2 2 3
1 2
5 5 4 8 3
5 1
6 2 1 4 4
7
Hình 3.3.7
Cho tập W = {1, 2, 3, 4}. Đồ thị <W> sinh bởi W có tập đỉnh {1, 2, 3, 4} và
tập cạnh là {(1,2),(2,3),(3,4),(4,1),(1,3)}. Dễ thấy rằng cây phủ nhỏ nhất của
<W> có các cạnh {(2,3),(3,4),(4,1)} với tổng trọng số là 9. Tuy nhiên cây với tập
đỉnh {1, 2, 3, 4, 5} và tập cạnh {(1,5),(5,2),(2,3),(3,4)} phủ W và có trọng số là 8
< 9.
Bây giờ ta sẽ xây dựng phương pháp giải bài toán Steiner bằng cách sử dụng
thuật toán Floyd-Warshall tìm khoảng cách và đường đi ngắn nhất và thuật toán
tìm cây phủ nhỏ nhất.
Định lý 3.3.4. Cho trọng đồ đơn đủ G với các đỉnh {1, 2, ..., n} và trọng số
w(i,j) thoả bất đẳng thức tam giác
w(i,j) w(i,k) + w(k,j) i, j, k
Cho W là tập m đỉnh trong G. Khi đó tồn tại cây Steiner của W trong G với
số điểm Steiner không vượt quá m2.
Chứng minh
Giả sử số đỉnh Steiner của W ứng với cây T là p. Khi đó T có (m+p) đỉnh và
(m+p1) cạnh. Ký hiệu x là bậc trung bình (trong T) của các điểm Steiner và y là
bậc trung bình (trong T) của các điểm không Steiner. Theo bổ đề bắt tay ta có
p.x + m.y = 2.(m+p1)
Mặt khác x 3 (theo bất đẳng thức tam giác) và y 1. Suy ra p m2.
Thuật toán 3.3.3. (Tìm cây Steiner)
Đầu vào. Trọng đồ liên thông G=(V,E,w) n đỉnh, và tập W V m đỉnh, m < n.
Đầu ra. Cây Steiner của W trong G.
Các bước.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.24
- Bước 1. Xây dựng trọng đồ đơn đủ G’=(V,F,w’) (bằng thuật toán Floyd-
Warshall), trong đó w’(u,v) là khoảng cách ngắn nhất từ u đến v với mọi cặp
(u,v).
- Bước 2.
Với mỗi S VW , card(S) m2, tìm cây phủ nhỏ nhất của đồ thị
<WS> sinh bởi WS trong G’. Trong các cây phủ đó tìm cây T’ có trọng số
nhỏ nhất.
- Bước 3. Xây dựng cây Steiner T từ T’ bằng cách thay mỗi cạnh nối hai đỉnh
trong G’ bằng đường đi nối chúng với nhau trong G. Các đỉnh thuộc T mà không
thuộc W là những đỉnh Steiner.
Ví dụ 3.3.4. Tìm cây Steiner của tập đỉnh W = {3,6,7} trong đồ thị cho ở ví dụ
3.3.3 (Hình 3.3.7).
Ma trận khoảng cách của đồ thị trên là
D =
0416532
4036752
1305421
6650354
5743025
3525203
2214530
Vì m = card(W) = 3, nên các tập S sẽ là các tập con của {1,2,4,5} với nhiều
nhất là 1 phần tử. Các tập SW sẽ là W1= {3,6,7}, W2 = {3,6,7,1}, W3 =
{3,6,7,2}, W4 = {3,6,7,4}, W5 = {3,6,7,5}. Các cây phủ trọng số nhỏ nhất của các
đồ thị sinh bởi W1, ..., W5 trong G’ có trọng số tương ứng là 9, 9, 9, 12 và 8.
Vậy ta sẽ chọn đồ thị sinh bởi W5 có cây phủ nhỏ nhất như sau
7
1 3
4
5
3
6 Hình 3.3.8
Cạnh (3,5) trong cây T’ thay bằng đường đi ngắn nhất 5-2-3. Tương tự, cạnh
(5,6) trong cây T’ thay bằng đường đi ngắn nhất 5-1-6.
Cuối cùng ta nhận được cây Steiner sau
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.25
7 2 2 3
1 2
5 1
6 2 1 Hình 3.3.9
Các điểm Steiner là 1, 2 và 5.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.26
IV. CÂY NHỊ PHÂN TÌM KIẾM
1. Cây nhị phân
Định nghĩa 3.4.1
Cây nhị phân là một dạng cấu trúc cây quan trọng, mỗi nút của nó chỉ có tối
đa hai nút con.
Với mỗi nút trên cây nhị phân, cây con xuất phát từ nút con trái gọi là cây
con trái và cây con xuất phát từ nút con phải gọi là cây con phải của nó.
Ví dụ 3.4.1. Trong các cây sau, (A) là cây nhị phân, (B) là cây nhị phân đầy đủ,
(C) là cây nhị phân đầy đủ cân bằng.
(A) (B) (C)
Hình 3.4.1
Từ các tính chất của cây m-phân ở mục trên ta suy ra
Định lý 3.4.1
Số lượng tối đa các nút mức k (k 1) trên cây nhị phân là 2k.
Số lượng tối đa các nút trên cây nhị phân độ cao h là 2h+11.
2. Duyệt cây
Phép duyệt cây là lần lượt đi qua tất cả các nút và mỗi nút chỉ qua 1 lần. Có
6 cách duyệt cây dựa vào thứ tự duyệt của các nút bên trái (L), nút gốc (N) và
các nút bên phải (R) là:
- Thứ tự Preorder : NLR, NRL (nút gốc trước)
- Thứ tự Inorder : LNR, RNL (nút gốc giữa)
- Thứ tự Postorder : LRN, RLN (nút gốc sau)
Ví dụ 3.4.2. Duyệt cây nhị phân sau:
A
B H
C D K L
E F Hình 3.4.2
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.27
Giả sử A là nút gốc, khi đó ta có các kết quả duyệt như sau:
NLR : ABCDEFHKL NRL : AHLKBDFEC
LNR : CBEDFAKHL RNL : LHKAFDEBC
LRN : CEFDBKLHA RLN : LKHFEDCBA
Ta nhận thấy thứ tự của NLR ngược với RLN, LNR ngược với RNL, LRN
ngược với NRL. Do đó ta chỉ xét ba phép duyệt cơ bản là NLR, LNR, LRN.
Thuật toán 3.4.1. Duyệt cây theo thứ tự NLR - Preorder. (Giải thuật đệ qui)
Đầu vào. Gốc r của cây nhị phân
Đầu ra. Danh sách dữ liệu ở các nút
Phương pháp. NLR
(i) Duyệt gốc
(ii) Duyệt cây bên trái
(iii) Duyệt cây bên phải
Thuật toán 3.4.2. Duyệt cây theo thứ tự LNR - Inorder: (Giải thuật đệ qui)
Đầu vào. Gốc r của cây nhị phân
Đầu ra. Danh sách dữ liệu ở các nút
Phương pháp.
(i) Duyệt cây bên trái
(ii) Duyệt gốc
(iii) Duyệt cây bên phải
Thuật toán 3.4.3. Duyệt cây theo thứ tự LRN - Postorder: (Giải thuật đệ qui)
Đầu vào. Gốc r của cây nhị phân
Đầu ra. Danh sách dữ liệu ở các nút
Phương pháp.
(i) Duyệt cây bên trái
(ii) Duyệt cây bên phải
(iii) Duyệt gốc
3. Cây nhị phân tìm kiếm (binary search tree)
Cây nhị phân tìm kiếm là cây nhị phân trong đó dữ liệu được gán với các
nút và dữ liệu được sắp xếp theo khóa sao cho khóa tại mỗi nút của cây lớn hơn
khóa của các nút cây con bên trái và nhỏ hơn hoặc bằng khóa của các nút cây
con bên phải.
Gọi
Kn - khoá nút xét
Kl - khoá nút con bên trái
Kr - khoá nút con bên phải
Khi đó ta có
Kl < Kn Kr
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.28
Như vậy theo định nghĩa thì khi duyệt cây nhị phân tìm kiếm theo thứ tự
Inorder - LNR ta được dãy có thứ tự khoá tăng dần.
Ví dụ 3.4.3
8
7 9
3 11
2 5 10 13
1 4 6 12 14
Hình 3.4.3
Khi duyệt theo thứ tự Inorder - LNR ta có dãy
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Thuật toán 3.4.4. Xây dựng cây nhị phân tìm kiếm
Đầu vào. Danh sách dữ liệu s
Đầu ra. Cây nhị phân tìm kiếm T
Phương pháp.
(1) Xây dựng gốc:
Nếu danh sách s rỗng, T là cây rỗng (không đỉnh, không cạnh), kết thúc.
Ngược lại, lấy w là phần tử đầu của danh sách s, ta xây dựng cây T có 1
đỉnh là gốc và lưu w tại gốc đó.
(2) Loại w khỏi s
(3) Xét phần tử tiếp theo:
Nếu danh sách s rỗng, kết thúc.
Ngược lại, lấy w là phần tử đầu của danh sách s và đặt nút v ban đầu là
gốc.
(4) Tìm vị trí lưu dữ liệu:
Nếu khóa của w nhỏ hơn khóa dữ liệu tại v, sang bước (5).
Ngược lại sang bước (6).
(5) Tìm bên trái:
Nếu v không có nút con trái, thêm nút con trái của v và lưu w tại đó,
quay lại (2).
Ngược lại, đặt v là nút con trái của v, quay lại (4).
(6) Tìm bên phải:
Nếu v không có nút con phải, thêm nút con phải của v và lưu w tại đó,
quay lại (2).
Ngược lại, đặt v là nút con phải của v, quay lại (4).
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.29
Cây nhị phân tìm kiếm được sử dụng để sắp xếp và tìm kiếm dữ liệu. Như
trên đã thấy, nếu dữ liệu được lưu trong cây nhị phân tìm kiếm thì duyệt cây theo
phương pháp Inorder ta sẽ được danh sách dữ liệu sắp xếp tăng dần theo khóa.
Bây giờ cho khóa K bất kỳ ta có thể xác định xem dữ liệu với khóa K có nằm
trong cây nhị phân tìm kiếm hay không bằng thuật toán sau:
Thuật toán 3.4.5. Tìm kiếm dữ liệu trong cây nhị phân tìm kiếm
Đầu vào: Cây nhị phân tìm kiếm T và khóa K
Đầu ra: Kết luận K không có trong cây T hoặc xác định vị trí chứa khóa K
Phương pháp:
(1) Xuất phát:
Đặt nút v ban đầu là gốc.
(2) Kiểm tra khóa:
Nếu K bằng khóa dữ liệu tại v, nút v là vị trí chứa dữ liệu với khóa K,
kết thúc.
(3) Tìm vị trí lưu dữ liệu:
Nếu khóa K nhỏ hơn khóa dữ liệu tại v, sang bước (4).
Ngược lại sang bước (5).
(4) Tìm bên trái:
Nếu v không có nút con trái, kết luận: khóa K không có trong cây T, kết
thúc.
Ngược lại, đặt v là nút con trái của v, quay lại (2).
(5) Tìm bên phải:
Nếu v không có nút con phải, kết luận: khóa K không có trong cây T, kết
thúc.
Ngược lại, đặt v là nút con phải của v, quay lại (2).
Ta thấy rằng thời gian tìm kiếm sẽ lớn nhất nếu khóa K không có trong cây T
và ta phải đi theo đường đi dài nhất từ gốc đến lá. Như vậy thời gian tìm kiếm
cực đại sẽ tỉ lệ với độ cao của cây T. Như vậy, nếu độ cao của cây thì việc tìm
kiếm sẽ rất nhanh. Có nhiều phương pháp cân bằng hóa làm cực tiểu độ cao của
cây.
Theo định lý ở mục 1, số lượng n các nút và độ cao h trong cây nhị phân
thỏa
n 2h+1
1
kéo theo
h log2(n+1) 1
Như vậy, nếu độ cao của cây nhị phân tìm kiếm cực tiểu thì độ phức tạp tìm
kiếm sẽ bằng log2(n+1) ( x ký hiệu số nguyên nhỏ nhất x ).
Chẳng hạn, ta có thể lưu 2000000 dữ liệu trong cây nhị phân tìm kiếm độ cao
21 vì
log2(2000000 + 1) = 21
Khi đó độ phức tạp tìm kiếm là 21.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.30
V. CÂY MÃ HUFFMAN
1. Mã tiền tố
Phương pháp biểu diễn ký hiệu trong máy tính phổ biến nhất là sử dụng
chuỗi các bit có độ dài cố định. Chẳng hạn ASCII biểu diễn mỗi ký hiệu bằng
xâu 8 bit (ví dụ A biểu diễn bằng xâu 01000001). Như vậy một bản tin có N ký
hiệu sẽ phải mã hóa bởi 8*N bit. Vậy có phương pháp mã hoá nào tiết kiệm hơn
không.
Giả sử ta có một bản tin gồm một dãy ký hiệu lấy trong một tập hợp hữu hạn
X. Biết rằng mỗi ký hiệu x trong bản tin xuất hiện theo một xác suất cho trước
p(x). Ta muốn mã hoá các ký hiệu này thành các chuỗi bit nhị phân sao cho chiều
dài chuỗi mã của bản tin là ngắn nhất.
Ví dụ 3.5.1. Xét bản tin gồm 1010
ký hiệu lấy từ tập X = {a,b,c,d,e,f}. Tần
suất xuất hiện các ký hiệu trong bản tin như sau:
Ký hiệu : a b c d e f
Tần suất (%) : 40 10 15 5 20 10
Ta có thể dùng xâu bit chiều dài cố định để mã hoá các ký tự. Chẳng hạn
Ký hiệu : a b c d e f
Mã I : 000 001 010 011 100 101
Cách mã hoá này cho chiều dài bản tin mã hóa là 3*1010
bit.
Cách mã thứ hai là
Ký hiệu : a b c d e f
Mã II : 0 01 00 11 1 10
Cách mã hoá này cho chiều dài bản tin mã hóa là
1010
(1*40+2*10+2*15+2*5+1*20+2*10)/100=1,4*1010
(bit)
Cách mã II rút ngắn bản tin hơn một nửa so với cách mã I. Tuy nhiên cách này dễ
dẫn đến nhầm lẫn, chẳng hạn dãy aa và ký tự c cùng một mã là 00.
Bây giờ ta xem cách mã sau:
Ký hiệu : a b c d e f
Mã III : 1 010 011 0010 000 0011
Cách mã hoá này cho chiều dài bản tin mã hóa là
1010
(1*40+3*10+3*15+4*5+3*20+4*10)/100=2,35*1010
(bit)
Cách mã III ngắn hơn cách mã I và có tính chất sau:
Không có chuỗi mã của ký hiệu nào là tiền tố (tức dãy con đầu) của chuỗi
mã của ký hiệu khác.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.31
Định nghĩa 3.5.1
Mã nhị phân của tập ký hiệu thoả tính chất trên gọi là mã tiền tố.
Với mỗi mã tiền tố ta có thể xây dựng cây nhị phân sao cho mỗi lá ứng với
một ký hiệu và đường đi từ gốc đến lá sẽ xác định mã của ký hiệu tương ứng như
sau:
Cạnh đi xuống con bên trái ứng với bit 0 và cạnh đi xuống con bên phải ứng
với bit 1.
Ví dụ 3.5.2. Cây nhị phân của mã tiền tố III ở ví dụ trước là:
0 1
a
0 1
0 1 0 1
e b c
0 1
d f
Hình 3.5.1
Đảo lại, xét cây nhị phân T, trên đó mỗi lá được gán nhãn là một ký hiệu
trong X. Khi đó cây T sẽ xác định một mã tiền tố. Với mỗi lá x, mức h(x) của x
chính là chiều dài chuỗi mã của x. Gọi f(x) là tần suất xuất hiện của ký hiệu x thì
chiều dài chuỗi mã bản tin là
Xx
xfxhL )(*)(*
trong đó L là số ký hiệu của bản tin. Đại lượng
Xx
xfxhTE )(*)()(
gọi là hệ số mã hóa.
Độ dài chuỗi mã bản tin ngắn nhất khi và chỉ khi cây T có hệ số mã hóa nhỏ
nhất. Cây T như vậy gọi là cây mã tối ưu.
Sau đây là giải thuật Huffman tìm cây mã tối ưu.
2. Giải thuật Huffman
Thuật toán 3.5.1. Giải thuật Huffman
Đầu vào. Tập ký hiệu X và bảng tần suất f(x) với mọi xX.
Đầu ra. Cây mã tối ưu Huffman.
Các bước.
(i) T là rừng có n =X cây, mỗi cây có đúng 1 đỉnh tương ứng với một
ký hiệu trong X. Gán mỗi gốc x một nhãn f(x).
(ii) Nếu T là cây thì dừng: T là cây mã tối ưu; ngược lại sang bước (iii)
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.32
(iii) Tìm hai cây trong T với nhãn gốc nhỏ nhất. Gọi các gốc là u và v. Nối
u và v với đỉnh w ta được cây mới gốc w (các cây u và v trở thành cây
con của w). Nhãn gán cho w là tổng nhãn của u và v. Quay lại bước (ii).
Bổ đề 3.5.1. Gọi x và y là hai ký hiệu có tần suất xuất hiện f(x), f(y) nhỏ nhất
trong X. Khi đó tồn tại cây mã tối ưu T của X sao cho x và y là hai nút anh em
trong T.
Chứng minh.
Gọi T0 là một cây mã tối ưu của X.
Giả sử x, y không là lá anh em. Gọi u là lá có mức lớn nhất trong T0. Khi đó u
phải có lá anh em v, vì nếu không ta có thể xoá nút u và gán ký hiệu u cho cha
của u và ta có mã mới tốt hơn T0 , mâu thuẫn với T0 là mã tối ưu.
Nếu x không cùng mức với u, tức h(x) < h(u), ta hoán đổi ký hiệu x và u và
nhận được cây mới T1. Ta có
E(T1) = E(T0) - h(x).f(x) - h(u).f(u) + h(x).f(u)+h(u).f(x) =
= E(T0) - [h(u)-h(x)].[f(u)-f(x)] < E(T0)
Điều này mâu thuẫn với tính tối ưu của T0. Vậy x và tương tự y có cùng mức
với u,v. Bằng cách hoán đổi x với u và y với v ta nhận được cây T có E(T) =
E(T0), nghĩa là T cũng là cây tối ưu.
Định lý 3.5.2. Giải thuật Huffman cho cây mã tối ưu.
Chứng minh.
Quy nạp theo số ký hiệu n của X.
+ Bước cơ sở: n=2. Giả sử hai ký hiệu trong X là x và y thì giải thuật cho cây
mã
0 1
x y Hình 3.5.2
và hiển nhiên đây là cây mã tối ưu.
+ Bước quy nạp: Giả sử X có n ký hiệu và x và y là hai ký hiệu có tần suất
nhỏ nhất.
Gọi X’ là tập có n1 ký hiệu nhận được từ X bằng cách thay ký hiệu x và y
bằng 1 ký hiệu z với tần suất f(z)=f(x)+f(y).
Theo bổ đề tồn tại cây mã tối ưu T sao cho x và y là anh em. Từ T bỏ hai nút
lá x và y và gán z cho nút cha của x và y ta nhận được cây mã T’ của X’.
Bây giờ cho H là cây nhận được từ giải thuật Huffman của X với x và y là
anh em. Từ H bỏ hai nút lá x và y và gán z cho nút cha của x và y ta nhận được
cây mã Huffman H’ của X’. Theo giả thiết quy nạp H’ là cây mã tối ưu. Vì vậy ta
có
E(H) = E(H’) + f(x) + f(y) E(T’) + f(x) + f(y) = E(T)
Mặt khác vì T tối ưu nên từ đó suy ra E(H) = E(T), tức là H tối ưu.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.33
Ví dụ 3.5.3. Xét ví dụ với bảng ký hiệu và tần suất như sau:
Ký hiệu : a b c d e f
Tần suất (%) : 40 10 15 5 20 10
Cây nhị phân của mã Huffman được xây dựng qua các bước:
Khởi tạo: Rừng T có 6 cây có gốc là a, b, c, d, e, f với các nhãn được ghi trong
ngoặc.
a(40)
e(20) c(15) f(10)
d(5) b(10) Hình 3.5.3
Bước 1: Gốc d và b có nhãn nhỏ nhất, nối chúng vào gốc db. Rừng T có 5 cây có
gốc là a, e, db, c, f
a(40)
e(20) db(15) c(15) f(10)
d(5) b(10) Hình 3.5.4
Bước 2: Gốc f và c có nhãn nhỏ nhất, nối chúng vào gốc fc. Rừng T có 4 cây có
gốc là a, e, db, fc
a(40)
fc(25)
e(20) db(15) c(15) f(10)
d(5) b(10) Hình 3.5.5
Bước 3: Gốc db và e có nhãn nhỏ nhất, nối chúng vào gốc dbe. Rừng T có 3 cây
có gốc là a, dbe, fc
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.34
a(40)
dbe(35) fc(25)
e(20) db(15) c(15) f(10)
d(5) b(10) Hình 3.5.6
Bước 4: Gốc fc và dbe có nhãn nhỏ nhất, nối chúng vào gốc fcdbe. Rừng T có 2
cây có gốc là a, fcdbe
fcdbe(60) a(40)
dbe(35) fc(25)
e(20) db(15) c(15) f(10)
d(5) b(10) Hình 3.5.7
Bước 5: Nối a và fcdbe vào gốc afcdbe. T là cây mã tối ưu:
afcdbe(100)
0 1
fcdbe(60) a(40)
0 1
dbe(35) fc(25)
0 1 0 1
e(20) db(15) c(15) f(10)
0 1
d(5) b(10) Hình 3.5.8
Mã Huffman tương ứng như sau:
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.35
Ký hiệu : a b c d e f
Mã Huffman : 1 0011 010 0010 000 011
Cách mã hoá này cho chiều dài bản tin là
1010
(1*40+4*10+3*15+4*5+3*20+3*10)/100=2,35*1010
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.36
VI. CÂY QUYẾT ĐỊNH
Các cây có gốc có thể dùng để mô hình hóa các bài toán trong đó có một dãy
các quyết định dẫn đến lời giải.
Định nghĩa 3.6.1. Cây có gốc trong đó mỗi đỉnh tương ứng với một quyết định
và mỗi cây con tại các đỉnh này ứng với một kết cục có thể của quyết định được
gọi là cây quyết định.
Bài toán 5 đồng tiền
Có 5 đồng tiền bằng kim loại hoàn toàn giống nhau, trong đó có một đồng
tiền giả nặng hơn hoặc nhẹ hơn các đồng tiền thật khác. Người ta dùng cân cân
bằng so sánh các đồng tiền để xác định đồng tiền giả.
Các đồng tiền ký hiệu là C1, C2, C3, C4, C5. Một phương pháp giải bài toán
cho ở cây quyết định sau.
C1 : C2
C1 : C5 C3 : C4 C1 : C5
C1,H C2,L C2,H C1,L
C3 : C5 C1 : C5 C3 : C5
C3,H C4,L C5,L C5,H C4,H C3,L
Hình 3.6.1
Các nút biểu diễn các lần cân so sánh đồng tiền Ci (trái) và Cj (phải). Các
nhãn trên cạnh có ý nghĩa như sau
đồng tiền trái nặng hơn đồng tiền phải
đồng tiền phải nặng hơn đồng tiền trái
hai đồng tiền trái nặng bằng nhau
Các lá nhãn Ci,H nghĩa là đồng tiền Ci nặng, các lá nhãn Ci,L nghĩa là đồng
tiền Ci nhẹ.
Chẳng hạn, tại gốc, ta so sánh C1 với C2 , nếu bên trái nặng hơn, ta biết hoặc
C1 là đồng tiền nặng, hoặc C2 là đồng tiền nhẹ. Theo cây quyết định, ta so sánh
C1 với C5 (là đồng tiền thật), nếu bên trái nặng hơn thì C1 là đồng tiền giả nặng,
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.37
nếu hai bên bằng nhau thì C2 là đồng tiền giả nhẹ (vì C là đồng tiền thật có
trọng lượng bằng C5 ).
Ta coi số lần cân so sánh tối thiểu trong trường hợp xấu nhất là độ phức tạp
thuật toán. Thuật toán trên là tối ưu. Thật vậy giả sử tồn tại thuật toán giải bài
toán 5 đồng tiền với số lần cân trong trường hợp xấu nhất nhỏ hơn 3. Khi đó cây
quyết định biểu diễn thuật toán T' là cây tam phân có độ cao 2. Số lá của T' sẽ
nhỏ hơn hoặc bằng 32 = 9. Mặt khác số lá của T' phải biểu diễn các kết quả có thể
của bài toán: Ci,H và Ci,L với i=1,...,5. Số kết quả này là 10 cho nên cây T' không
thể giải hết các trường hợp của bài toán.
Bài toán 4 đồng tiền
Bài toán 4 đồng tiền cũng có độ phức tạp là 3.
Thật vậy, nếu ta so sánh cặp C1, C2 với cặp C3, C4 thì sau hai lần cân có tối
đa 6 lá kết quả (xem hình), trong khi lời giải yêu cầu có 2*4=8 kết quả.
C1 C2 : C3C4
không
tồn
tại
cạnh
6 kết quả Hình 3.6.2
Ngược lại, nếu ta so sánh C1 với C2 thì trong trường hợp hai đồng tiền nặng
bằng nhau, một lần cân so sánh nữa chỉ cho tối đa 3 lá kết quả (xem hình sau),
trong khi số kết quả có thể của nhánh này là 4: C3,H ; C3,L ; C4,H ; C4,L.
C1 : C2
3 kết quả
Hình 3.6.3
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.38
BÀI TẬP I. CÁC KHÁI NIỆM CƠ BẢN
3.1.1. Vẽ tất cả các cây không đẳng cấu với nhau
(a) có 4 đỉnh; (b) có 5 đỉnh; (c) có 6 đỉnh
3.1.2. Tìm các giá trị của m và n để đồ thị lưỡng phân đầy đủ Km,n là cây.
3.1.3. Cho đồ thị G là rừng có t cây và n đỉnh. Tính số cạnh của G.
3.1.4. Cây ngũ phân đầy đủ với 100 đỉnh trong có bao nhiêu đỉnh tất cả ?
3.1.5. Cây nhị phân đầy đủ với 1000 đỉnh trong có bao nhiêu cạnh tất cả ?
3.1.6. Cây tam phân đầy đủ với 100 đỉnh trong có bao nhiêu lá tất cả ?
3.1.7. Giả sử có 1000 đội bóng tham gia một giải với phương thức loại trực tiếp,
cho đến khi tìm được 1 đội vô địch. Hãy lập mô hình các trận đấu để xác định số
trận đấu phải tổ chức.
II. CÂY PHỦ
3.2.1. Sử dụng thuật toán tìm kiếm ưu tiên chiều sâu tìm cây phủ, với gốc a, của
các đồ thị sau
(a) a e f g
c d
b h i j
(b) b c d e f
a
g h i j k
l m n
(c) a b c d e
f g i j k l
m n o p q u
r s t
3.2.2. Sử dụng thuật toán tìm kiếm ưu tiên chiều rộng tìm cây phủ, với gốc a, của
các đồ thị cho ở bài tập 3.2.1.
3.2.3. Đồ thị cho bởi ma trận kề sau có liên thông không
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.39
a b c d e f g
a 0 0 1 0 1 0 0
b 0 0 0 1 0 1 0
c 1 0 0 0 1 0 0
d 0 1 0 0 0 1 1
e 1 0 1 0 0 0 1
f 0 1 0 1 0 0 1
g 0 0 0 1 1 1 0
3.2.4. Gọi G là đồ thị 25 đỉnh {1, 2, . . . , 25}. Đỉnh i kề đỉnh j nếu i khác j và
không nguyên tố cùng nhau. Đồ thị G có bao nhiêu thành phần liên thông, tìm
cây bao trùm của các thành phần liên thông của G.
III. CÂY PHỦ NHỎ NHẤT
3.3.1. Dùng thuật toán Prim tìm cây phủ nhỏ nhất của các đồ thị sau
(a) (b) a 1 b a 5 b 4 c
2 3 2 3 5 6 3
4 e 3
3 2 d 7 e 1 f
c 1 d 6 8 3 4 4
g 4 h 2 i
(c) (d) 2
a 2 2 b
1 2 1
2 1 1 3 3 1
c d 2 3 2
1 1
e 2 2 2 2 2 3
3 4
4 3
3 2
f g 3 4 3 2
2 2 3
h 2 2 i
2
3.3.2. Dùng thuật toán Kruskal tìm cây phủ nhỏ nhất của các đồ thị ở bài 3.3.1.
3.3.3. Chứng minh rằng nếu trọng số các cạnh của đồ thị liên thông G từng đôi
một khác nhau thì G có cây phủ nhỏ nhất duy nhất.
3.3.4. Cho đơn đồ thị đầy đủ G gồm n đỉnh {0, 1, 2, . . . , n1}. Giả sử trọng số
cạnh (i,j) là i j. Tìm cây phủ nhỏ nhất của G.
3.3.5. Cho đơn đồ thị đầy đủ G gồm n đỉnh {0, 1, 2, . . . , n1}. Giả sử trọng số
cạnh (i,j) là i + j. Tìm cây phủ nhỏ nhất của G.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.40
IV. CÂY NHỊ PHÂN TÌM KIẾM
3.4.1. a) Định nghĩa cây nhị phân tìm kiếm. Trình bày khai báo cây nhị phân bằng
cấu trúc con trỏ.
b) Viết thủ tục tạo cây nhị phân tìm kiếm T chứa n số nguyên không âm
ngẫu nhiên nhỏ hơn 1000 ( n < 1000 ) và khác nhau từng đôi một
c) Viết thủ tục duyệt cây T theo thứ tự Inorder-LNR.
V. CÂY MÃ HUFFMAN
3.5.1. Xây dựng cây mã Hufman cho tập ký hiệu sau
Ký hiệu: A B C D E F G H
Tần suất: 6 25 20 8 10 19 3 9
BÀI TẬP THỰC HÀNH MÁY TÍNH
B.3.1. Viết chương trình cài đặt thuật toán tìm cây phủ theo chiều sâu.
B.3.2. Viết chương trình cài đặt thuật toán tìm cây phủ theo chiều rộng.
B.3.3. Viết chương trình cài đặt thuật toán duyệt đồ thị vô hướng.
B.3.4. Viết chương trình cài đặt thuật toán duyệt đồ thị có hướng.
B.3.5. Viết chương trình cài đặt thuật toán sắp xếp tô-pô đồ thị có hướng.
B.3.6. Viết chương trình cài đặt thuật toán tìm thành phần liên thông mạnh.
B.3.7. Viết chương trình cài đặt thuật toán định hướng mạnh đồ thị vô hướng.
B.3.8. Viết chương trình cài đặt thuật toán Prim.
Hướng dẫn cài đặt chương trình:
Khai báo:
oo = MaxInt; {vo cung}
n là số đỉnh;
m là số cạnh;
dau[i], cuoi[i], trongso[i] là đỉnh đầu, đỉnh cuối và trọng số cạnh thứ i, i=1,...,
m.
chondinh[i] = true đánh dấu đỉnh i đã được chọn, i=1..n.
choncanh[i] = true đánh dấu cạnh i đã được chọn, i=1..m.
LienThong : boolean;
v : integer; đỉnh gốc đọc từ file
Procedure Input;
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.41
Procedure Init;
begin
for i := 1 to n do chondinh[i] := false;
for j := 1 to m do choncanh[j] := false;
chondinh[v] := true;
SoDinhChon := 1;
TongTrongSo := 0;
LienThong := true;
end;
Procedure Prim;
var a, b, i : integer;
begin
repeat
min := oo;
for i := 1 to m do
if ((chondinh[dau[i]] and not chondinh[cuoi[i]]) or
(not chondinh[dau[i]] and chondinh[cuoi[i]])) and
(trongso[i] < min) then
begin
min := trongso[i]; imin := i;
end;
if min = oo then LienThong := false
else
begin
choncanh[imin] := true;
chondinh[dau[imin]] := true;
chondinh[cuoi[imin]] := true;
TongTrongSo := TongTrongSo + min;
SoDinhChon := SoDinhChon + 1;
end;
until (SoDinhChon = n) or (not LienThong);
end;
Procedure Output;
var i:integer;
begin
{mở file}
if LienThong then
begin
writeln(..., TongTrongSo);
for i := 1 to m do
if choncanh[i] then
writeln(..., dau[i], cuoi[i]);
end
else
writeln(..., "Đồ thị không liên thông");
{đóng file}
end;
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.42
{chuong trinh chinh}
begin
input;
init;
prim;
output;
end.
B.3.9. Viết chương trình cài đặt thuật toán Kruskal.
Hướng dẫn cài đặt chương trình:
Khai báo:
oo = MaxInt; {vo cung}
n là số đỉnh;
m là số cạnh;
dau[i], cuoi[i], trongso[i] là đỉnh đầu, đỉnh cuối và trọng số cạnh thứ i, i=1,...,
m.
tplt[i] : integer; số hiệu thành phần liên thông của đỉnh i trong T, i=1..n.
choncanh[i] = true đánh dấu cạnh i đã được chọn, i=1..m.
LienThong : boolean;
SoTPLT: integer; {số thành phần liên thông}
Procedure Input;
Procedure Init;
begin
for v := 1 to n do tplt[v] := v;
for v := 1 to m do choncanh[v] := false;
TongTrongSo := 0;
SoTPLT := n;
end;
Procedure CapNhatTPLT(x, y:integer);
Var i:integer;
Begin
for i := 1 to n do
if tplt[i] = y then tplt[i] := x;
End;
Procedure Kruskal;
var i : integer;
begin
repeat
min := oo;
for i := 1 to m do
if (tplt[dau[i]] <> tplt[cuoi[i]]) and (trongso[i] < min) then
begin
min := trongso[i]; imin := i;
end;
if min = oo then LienThong := false
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.43
else
begin
choncanh[imin] := true;
CapNhatTPLT(tplt[dau[imin]], tplt[cuoi[imin]]);
SoTPLT := SoTPLT – 1;
TongTrongSo := TongTrongSo + min;
end;
until (SoTPLT = 1) or (not LienThong);
end;
Procedure Output;
var i:integer;
begin
{mở file}
if LienThong then
begin
writeln(..., TongTrongSo);
for i := 1 to m do
if choncanh[i] then
writeln(..., dau[i], cuoi[i]);
end
else
writeln(..., "Đồ thị không liên thông");
{đóng file}
end;
{chuong trinh chinh}
begin
input;
init;
Kruskal;
output;
end.
B.3.10. Cài đặt thuật toán duyệt cây theo thứ tự NLR - Preorder.
Hướng dẫn
Procedure Traverse_NLR(p: pointer);
begin
if p <> nil then
begin
write(p^.Info);
Traverse_NLR(p^.Left);
Traverse_NLR(p^.Right);
end;
end;
B.3.11. Cài đặt thuật toán duyệt cây theo thứ tự LRN – Postorder.
Hướng dẫn
Procedure Traverse_LNR(p:pointer);
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.44
begin
if p <> nil then
begin
Traverse_LNR(p^.Left);
write(p^.Info);
Traverse_LNR(p^.Right);
end;
end;
B.3.12. Cài đặt thuật toán duyệt cây theo thứ tự LRN – Postorder.
Hướng dẫn
Procedure Traverse_LRN(p:pointer);
begin
if p <> nil then
begin
Traverse_LRN(p^.Left);
Traverse_LRN(p^.Right);
write(p^.Info);
end;
end;
B.3.13. Cài đặt thuật toán 3.4.4 xây dựng cây nhị phân tìm kiếm
B.3.14. Cài đặt Thuật toán 3.4.5 tìm kiếm dữ liệu trong cây nhị phân tìm kiếm.
B.3.15. Cài đặt chương trình tìm cây mã Hufman với
- file dữ liệu đầu vào
HUFFMAN.INP có cấu trúc
n số ký hiệu
x1 t1 ký hiệu và tần suất thứ 1
x2 t2 ký hiệu và tần suất thứ 2
........
xn tn ký hiệu và tần suất thứ n
- file dữ liệu đầu ra
HUFFMAN.OUT có cấu trúc
e hệ số mã hóa tối ưu
x1 m1 ký hiệu và mã thứ 1
x2 m2 ký hiệu và mã thứ 2
........
xn mn ký hiệu và mã thứ n
Hướng dẫn
+ Khai báo cấu trúc nút cây như sau
pointer kiểu con trỏ trỏ đến nút cây mã
nodetype kiểu nút gồm các trường
{ ký hiệu symbol, (char)
tần suất frequency, (float)
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.45
chỉ số nút trái left, (int)
chỉ số nút phải right, (int)
mã tiền tố code, (mảng ký tự)
nhãn nút gốc isroot (isroot = 1 hoặc 0 đánh dấu nút là gốc hoặc
không phải gốc)
nhãn leftvisited (leftvisited = 1 hoặc 0 đánh dấu nhánh trái đã
thăm hoặc chưa thăm)
nhãn rightvisited (rightvisited = 1 hoặc 0 đánh dấu nhánh phải
đã thăm hoặc chưa thăm)
}
node[i] kiểu con trỏ pointer, i=1,...,2n1 (cây mã tiền tố có 2n1 nút)
+ Khởi tạo:
Đọc file HUFFMAN.INP
Tạo các nút node[i], i=1,...,n, nạp dữ liệu của n ký hiệu.
+ Xây dựng cây mã tối ưu:
Vòng lặp (m chạy từ n+1 đến 2n1 ) thực hiện:
{ - Tìm hai nút gốc m1, m2 (1 m1 m2 m1) có tần suất t nhỏ nhất:
{ min1:= ; min2 := ; m1 := 0; m2 := 0;
Vòng lặp (i chạy từ 1 đến m1 ) thực hiện:
{ nếu node[i]isroot =1 thì
{ nếu node[i]frequency < min1 thì
{ min2 := min1; min1:= node[i]frequency;
m2 := m1; m1 := i
}
nếu min1 node[i] frequency < min2 thì
{ min2:= node[i]frequency; m2 := i }
}
}
}
- Tạo nút node[m]
{ node[m]frequency := min1+min2;
node[m]left := m1;
node[m]right := m2;
node[m]isroot := 1;
node[m]leftvisited := 0;
node[m]rightvisited := 0;
node[m1]isroot := 0;
node[m2]isroot := 0;
}
}
+ Tạo mã Huffman: duyệt cây gốc node[2n1] tương tự phương pháp tìm
cây phủ theo chiều sâu.
Trong thuật giải này ta ký hiệu S là ngăn xếp (stack) các chỉ số đỉnh, code là
mảng các bít chứa mã, length là độ dài mã, m số ký hiệu được mã hóa, e là
hệ số mã hóa tối ưu.
(i) Khởi tạo:
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.46
Khởi tạo ngăn xếp S := [2n1], length := 0, m := 0. e := 0;
(ii) while (m < n)
{Xét pS.
Nếu (p <= n) thì (ghi mã cho nút lá)
{ node[p]code := code[1..length];
e := e + node[p]frequency*length;
Đẩy p ra khỏi ngăn xếp S.
length := length 1;
m := m + 1;
}
Ngược lại
Nếu (node[p]->leftvisited = 1) & (node[p]->rightvisited = 1) thì (quay lui)
{
Đẩy p ra khỏi ngăn xếp S.
length := length 1;
}
Ngược lại
Nếu (node[p]leftvisited = 0) thì (thăm nhánh trái)
{ node[p]leftvisited := 1;
Đẩy node[p]left vào ngăn xếp S.
length := length +1;
code[length] := ‘0’;
}
Ngược lại thì (thăm nhánh phải)
{ node[p]rightvisited := 1;
Đẩy node[p]right vào ngăn xếp S.
length := length +1;
code[length] := ‘1’;
}
} (kết thúc while)
+ Kết xuất mã:
Mở file kết quả;
Kết xuất hệ số nén e;
Vòng lặp (m chạy từ 1 đến n ) thực hiện:
{ Xuống dòng;
Kết xuất node[m]symbol;
Kết xuất node[m]code;
}
Đóng file kết quả;
B.3.16. Cµi ®Æt ch¬ng tr×nh t×m rõng phñ nhá nhÊt.
§Çu vµo: Träng ®å G. §Çu ra: Rõng phñ nhá nhÊt. Ph¬ng ph¸p:
- Giai ®o¹n 1: T×m thµnh phÇn liªn th«ng cña ®å thÞ G.
- Giai ®o¹n 2: T×m c©y phñ nhá nhÊt cho mçi thµnh phÇn liªn th«ng cña G.
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.47
Hướng dẫn cài đặt chương trình tìm các thành phần liên thông:
Khai báo:
n là số đỉnh;
m là số cạnh;
dau[i], cuoi[i] là đỉnh đầu, đỉnh cuối cạnh thứ i, i=1,..., m.
tplt[i] : integer; số hiệu thành phần liên thông của đỉnh i trong T, i=1..n.
SoTPLT:integer; số thành phần liên thông.
Procedure Input;
{nhập dữ liệu đầu vào từ bàn phím hoặc file: n, m, dau[i], cuoi[i], i=1, …, m }
Procedure Init;{khởi tạo}
begin
for v := 1 to n do
tplt[v] := v;
SoTPLT := n;
end;
Procedure CapNhatTPLT(x, y:integer);
var i:integer;
begin
for i := 1 to n do
if tplt[i] = y then tplt[i] := x;
for i := 1 to n do
if tplt[i] = SoTPLT then tplt[i] := y;
end;
Procedure TPLT;
var i, x, y : integer;
begin
for i := 1 to m do
if (tplt[dau[i]] <> tplt[cuoi[i]]) then
begin
x := min(tplt[dau[i]], tplt[cuoi[i]]);
y := max(tplt[dau[i]], tplt[cuoi[i]]);
CapNhatTPLT(x, y);
SoTPLT := SoTPLT – 1;
end;
end;
Function min(x,y:integer):integer;
begin
if x < y then min := x
else min:= y;
end;
Function max(x,y:integer):integer;
begin
Trần Quốc Chiến Lý thuyết đồ thị và ứng dụng
Chương III. Cây III.48
if x > y then max := x
else max := y;
end;
Procedure Output;
var i:integer;
begin
{mở file}
<Ghi SoTPLT>;
for i := 1 to SoTPLT do
begin
<xuống dòng>
for j := 1 to n do
if tplt[j] = i then <Ghi(j)>;
end;
{đóng file}
end;
{chương trình chính}
begin
input;
init;
TPLT;
output;
end.