Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Chương 1
MỘT SỐ KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ
I. MỘT SỐ KHÁI NIỆM CƠ BẢN CỦA LÝ THUYẾT ĐỒ THỊ 1. Định nghĩa đồ thị
Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối các đỉnh này, các loại đồ thị khác nhau được phân biệt bởi kiểu và số lượng cạnh nối hai đỉnh nào đó của đồ thị.
Giả sử V là tập hữu hạn, không rỗng các phần tử nào đó. Bộ G = (V,E) được gọi là đồ thị hữu hạn. Mỗi phần tử của V gọi là một đỉnh và mỗi phần tử u = (x,y) của E được gọi là một cạnh của đồ thị G = (V,E). Xét một cạnh u của E khi đó tồn tại hai đỉnh x, y của V sao cho u = (x,y), ta nói rằng x nối với y hoặc x và y phụ thuộc u.
- Nếu cạnh u = (x,y) mà x và y là hai đỉnh phân biệt thì ta nói x, y là hai đỉnh kề nhau.
- Nếu u = (x,x) thì u là cạnh có hai đỉnh trùng nhau ta gọi đó là một khuyên. - Nếu u = (x,y) mà x, y là cặp đỉnh có phân biệt thứ tự hay có hướng từ x đến y
thì u là một cung, khi đó x là gốc còn y là ngọn hoặc x là đỉnh ra, y là đỉnh vào. - Khi giữa cặp đỉnh (x,y) có nhiều hơn một cạnh thì ta nói rằng những cạnh
b x y y y x
cùng cặp đỉnh là những cạnh song song hay là cạnh bội.
a) b) c) Hình 1.1
Thí dụ ở hình 1.1 (a) tại đỉnh y có một khuyên b. (b) là cung (x,y) có hướng. (c) cặp đỉnh (x,y) tạo thành cạnh bội.
Trong thực tế ta có thể gặp nhiều vấn đề mà có thể dùng mô hình đồ thị để biểu diễn, như sơ đồ mạng máy tính, sơ đồ mạng lưới giao thông, sơ đồ thi công một công trình.
Thí dụ 1. Xét một mạng máy tính, có thể biểu diễn mạng này bằng một mô hình đồ thị, trong đó mỗi máy tính là một đỉnh, giữa các máy được nối với nhau bằng các dây truyền, chúng tương ứng là các cạnh của đồ thị. Một mô hình mạng máy tính như hình 1.2 trong đó các máy tính a, b , c, d tương ứng là các đỉnh, giữa hai máy được nối trực tiếp với nhau thì tương ứng với một cặp đỉnh kề nhau.
1
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
a b
c d
Hình 1.2
Định nghĩa 1. Đơn đồ thị vô hướng G = (V,E) bao gồm V là các tập đỉnh và E là các 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. Thí dụ 2.
b e g a
d h c
l k i
Hình 2. Sơ đồ máy tính là đơn đồ thị vô hướng
b g e a
Trong trường hợp giữa hai máy tính nào đó thường xuyên phải tải nhiều thông tin người ta phải nối hai máy này bởi nhiều kênh thoại. Mạng với đa kênh thoại giữa các máy được cho trong hình 3.
d c h
l i
k Hình 3. Sơ đồ mạng máy tính với đa kênh thoại
Định nghĩa 2. Đa đồ thị vô hướng G = (V,E) bao gồm V là tập các đỉnh, và E là họ 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. Hai cạnh e1 và e2 được gọi là cạnh lặp nếu chúng cùng tương ứng với một cặp đỉnh.
2
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
a e g b
d c h
l i
k Hình 4. Sơ đồ mạng máy tính với đa kênh thông báo
Rõ ràng mỗi đơn đồ thị là đa đồ thị, nhưng không phải đa đồ thị nào cũng là đơn đồ thị, vì trong đa đồ thị có thể có hai (hoặc có nhiều hơn) cạnh nối một cặp đỉnh nào đó.
Trong mạng máy tính có thể có những kênh thoại nối một máy nào đó với chính nó (chẳng hạn với mục đích thông báo). Mạng như vậy được cho trong hình 4. Khi đó đa đồ thị không thể mô tả được mạng như vậy, bởi vì có những khuyên(cạnh nối một đỉnh với chính nó). Trong trường hợp này chúng ta cần sử dụng đến khái niệm giả đồ thị vô hướng, được định nghĩa như sau.
Định nghĩa 3. Giả đồ thị vô hướng G = (V,E) bao gồm V là các tập đỉnh, và E là họ các cặp không có thứ tự (không nhất thiết phải khác nhau) của V gọi là các cạnh. Cạnh e được gọi là khuyên nếu nó có dạng e = (u,u).
b g e a
d c h
Các kênh thoại trong mạng máy tính có thể chỉ cho phép truyền tin theo một chiều. Chẳng hạn trong hình 5 máy chủ ở a chỉ có thể nhận tin từ các máy ở máy khác, có một số máy chỉ có thể gửi tin đi, còn các kênh thoại cho phép truyền tin theo cả hai chiều được thay thế bởi hai cạnh có hướng ngược chiều nhau. l i
k Hình 5. Mạng máy với các kênh thoại một chiều
Ta đi đến định nghĩa sau. Định nghĩa 4. Đơn đồ thị có hướng G = (V,E) bao gồm V là các tập đỉnh và E
là các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung.
3
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Nếu trong mạng có thể có đa kênh thoại một chiều, ta sẽ phải sử dụng đến
khái niệm đa đồ thị có hướng:
Định nghĩa 5. Đa đồ thị có hướng G = (V,E) bao gồm V là các tập đỉnh và E là họ các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung. Hai cung e1, e2 tương ứng cùng với một cặp đỉnh được gọi là cung lặp.
Trong các phần tử tiếp theo chủ yếu chúng ta sẽ làm việc với đơn đồ thị vô hướng và đơn đồ thị có hướng. Vì vậy, để ngắn gọn, ta bỏ qua tính từ đơn khi nhắc đến chúng.
2. Các thuật ngữ cơ bản
Trong phần này chúng ta sẽ trình bày một số thuật ngữ cơ bản của lý thuyết đồ thị. Trước tiên, ta xét các thuật ngữ mô tả các đỉnh và cạnh của đồ thị vô hướng.
Định nghĩa 1. 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 là 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). Để có thể biết có bao nhiêu cạnh liên thuộc với một cạnh, ta đưa vào định nghĩa sau.
Định nghĩa 2. Ta gọi bậc của đỉnh v trong đồ thị vô hướng là số cạnh liên
d b c
thuộc với nó và sẽ ký hiệu là deg(v).
e f a g
Hình 1. Đồ thị vô hướng G
Thí dụ 1. Xét đồ thị trong hình 1 ta có.
deg(a) = 1, deg(b) = 4, deg(c) = 4, deg(f) = 3, deg(d) = 1, deg(e) = 3, deg(g) = 0.
Đỉnh bậc 0 gọi là đỉnh cô lập. Đỉnh bậc 1 gọi là đỉnh treo. Trong ví dụ trên
deg( v
2 m
)
đỉnh g là đỉnh cô lập, a và d là các đỉnh treo. Bậc của đỉnh có các tính chất sau:
Định lý 1. Giả sử G = (V,E) là đồ thị vô hướng với m cạnh. Khi đó Vv
4
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Chứng minh. Rõ ràng mỗi cạnh e = (u,v) được tính một lần trong deg(u) và một lần trong deg(v). Từ đó suy ra tổng tất cả các bậc của các đỉnh bằng hai lần số cạnh. Hệ quả. Trong đồ thị vô hướng, số đỉnh bậc lẻ (nghĩa là đỉnh có bậc là số lẻ)
2
m
deg(
v
)
deg(
v
)
deg(
v
)
Vv
Vv 1
Vv 2 Do deg(v) chẵn với v là đỉnh trong U nên tổng thứ hai trong vế phải ở trên là số chẵn. Từ đó suy ra tổng thứ nhất (chính là tổng bậc của các đỉnh lẻ) cũng phải là số chẵn, do tất cả các số hạng của nó sẽ là số lẻ nên tổng này phải gồm một số chẵn các số hạng. Vì vậy số đỉnh bậc lẻ phải là số chẵn.
Chứng minh. Thực vậy gọi V1 và V2 tương ứng là tập chứa các đỉnh bậc lẻ và là một số chẵn. tập chứa các đỉnh bậc chẵn của đồ thị. Ta có
Ta xét các thuật ngữ tương tự cho đồ thị có hướng.
Định nghĩa 3. Nếu e = (u,v) là cung của đồ thị có hướng G thì ta nói hai đỉnh u và v là kề nhau, và nói cung (u,v) nối đỉnh u với đỉnh v hoặc cũng nói cung này là đi ra khỏi đỉnh u và đi vào đỉnh v. Đỉnh u(v) sẽ được gọi là đỉnh đầu(cuối) của cung (u,v). Định nghĩa 4. Ta gọi bán bậc ra (bán bậc vào) của đỉnh v trong đồ thị có
b c a
e d
hướng là số cung của đồ thị đi ra khỏi nó (đi vào nó) và ký hiệu là deg+(v)(deg-(v)). Hình 2. Đồ Thị có hướng G
Thí dụ 3. Xét đồ thị cho trong hình 2. Ta có
deg-(a) = 1, deg-(b) = 2, deg-(c) = 2, deg-(d) = 2, deg-(e) = 2. deg+(a) = 3, deg+(b) = 1, deg+(c) = 1, deg+(d) = 2, deg+(e) = 2. Do mỗi cung (u,v) sẽ được tính một lần trong bán bậc vào của đỉnh v và một lần trong bán bậc ra của đỉnh u nên ta có:
deg
)( v
deg
)( v
|
E
|
Vv
Vv
Định lý 2. Giả sử G = (V,E) là đồ thị có hướng. Khi đó
5
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Rất nhiều tính chất của đồ thị có hướng không phụ thuộc vào hướng trên các cung của nó. Vì vậy, trong rất nhiều trường hợp sẽ thuận tiện hơn nếu ta bỏ qua hướng trên các cung của đồ thị. Đồ thị vô hướng thu được bằng cách bỏ qua hướng trên các cung được gọi là đồ thị vô hướng tương ứng với đồ thị có hướng đã cho.
3. Đường đi, chu trình. Đồ thị liên thông. Định nghĩa 1. Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số
x0, x1,…, xn-1, xn
(x0,x1), (x1,x2),…, (xn-1,xn).
nguyên dương, trên đồ thị vô hướng G = (V,E) là dãy Trong đó u = x0, v = xn, v = (xi, xi+1) E, i = 0,1,2,…, n-1. Đường đi nói trên còn có thể biểu diễn dưới dạng dãy các cạnh: Đỉ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. Đường đi hay chu trình được gọi là đơn nếu như không có cạnh nào bị lặp lại.
a b a b c c
d d e e f f
Thí dụ 1. Trên đồ thị vô hướng cho hình 1: a, d, c, f, e là đường đi đơn độ dài 4. Còn d, e, c, a không là đường đi, do (e,c) không phải là cạnh của đồ thị. Dãy b, c, f, e, b là chu trình độ dài 4. Đường đi a, b, e, d, a, b có độ dài là 5 không phải là đường đi đơn, do cạnh (a,b) có mặt trong nó hai lần.
Hình 3. Đường đi trên đồ thị
Khái niệm đường đi và chu trình trên đồ thị có hướng được định nghĩa hoàn toàn tương tự như trường hợp đồ thị vô hướng, chỉ khác là ta có chú ý đến hướng trên các cung.
Định nghĩa 2. Đường đi độ dài n từ đỉnh u đến đỉnh v, trong đó n là số
x0, x1,…, xn-1, xn
(x0, x1), (x1, x2), (xn-1, xn).
nguyên dương, trên đồ thị có hướng G = (V,A) là dãy trong đó u = x0, v = xn, (xi, xi+1) A, i = 0, 1, 2,…, n-1. Đường đi nói trên còn có thể biểu diễn dưới dạng dãy các cung: Đỉ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. Đường đi hay chu trình được gọi là đơn nếu như không có cạnh nào bị lặp lại.
6
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Thí dụ 2. Trên đồ thị có hướng cho ở hình 3: a d c f e là đường đi đơn độ dài 4. Còn d e c a không là đường đi, do (e,c) không phải là cạnh của đồ thị. Dãy b, c, f, e, b là chu trình độ dài 4. Đường đi a b e d a b có độ dài là 5 không phải là đường đi đơn, do cạnh (a,b) có mặt trong nó hai lần. Xét một mạng máy tính. Một câu hỏi đặt ra là hai máy tính bất kỳ trong mạng này có thể trao đổi thông tin được với nhau hoặc là trực tiếp qua kênh nối chúng hoặc thông qua một hoặc vài máy trung gian trong mạng? Nếu sử dụng đồ thị để biểu diễn mạng máy tính này (trong đó các đỉnh của đồ thị tương ứng với các máy tính, còn các cạnh tương ứng của các kênh nối) câu hỏi đó được phát biểu trong ngôn ngữ đồ thị như sau: Tồn tại hay chăng đường đi giữa mọi cặp đỉnh của đồ thị?
Định nghĩa 3. Đồ thị vô hướng G = (V,E) được gọi là liên thông nếu luôn tìm
được đường đi giữa hai đỉnh bất kỳ của nó. Như vậy hai máy tính bất kỳ trong mạng có thể trao đổi thông tin được với
nhau khi và chỉ khi đồ thị tương ứng với mạng này là đồ thị liên thông. Thí dụ 3. Trong hình 2: Đồ thị G là liên thông, còn đồ thị H là không liên
a b
H1 c
d e
H2 H3 g e
H G thông.
Hình 2. Đồ thị liên thông G và đồ thị H gồm 3 thành phần liên thông H1, H2, H3.
II. MỘT SỐ THUẬT TOÁN TRÊN ĐỒ THỊ 1 Thuật toán tìm kiếm trên đồ thị 1.1 Tìm kiếm theo chiều sâu trên đồ thị Ý tưởng chính của thuật toán có thể trình bày như sau. Ta sẽ bắt đầu tìm kiếm từ một đỉnh v0 nào đó của đồ thị. Sau đó chọn u là một đỉnh tuỳ ý kề với v0 và lặp lại quá trình đối với u. Ở bước tổng quát, giả sử ta đang xét đỉnh v, Nếu nhử tổng số các đỉnh kề với v tìm được đỉnh w là chưa được xét thì ta sẽ xét đỉnh này( nó sẽ trở thành đã xét) và bắt đầu từ nó ta sẽ tiếp tục quá trình tìm kiếm. Còn nếu như không còn đỉnh nào kề với v là chưa xét thì ta sẽ nói rằng đỉnh này là đã duyệt xong và quay trở
7
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
lại tiếp tục tìm kiếm từ đỉnh mà trước đó ta đến được đỉnh v (nếu v = v0, thì kết thúc tìm kiếm). Có thể nói nôm na là tìm kiếm theo chiều sâu bắt đầu từ đỉnh v được thực hiện trên cơ sở tìm kiếm theo chiều sâu từ tất cả các đỉnh chưa xét kề với v. Quá trình này có thể mô tả bởi thủ tục đệ qui sau đây.
Thăm_đỉnh(v); Chuaxet[v] := false; for u Ke(v) do if Chuaxet[u] then DFS(u); Procedure DFS(v); (* Tìm kiếm theo chiều sâu bắt đầu từ đỉnh v; Các biến Chuaxet, Ke, là toàn cục *) Begin end; (* đỉnh v là đã duyệt xong *)
Khi đó, tìm kiếm theo chiều sâu trên đồ thị được thực hiện nhờ thuật toán sau:
(* Initialiation *) for v V do Chuaxet[u] := true; for v V do if Chuaxet[v] then DFS(v);
BEGIN END.
Rõ ràng lệnh gọi DFS(v) sẽ cho phép đến thăm tất cả các đỉnh thuộc cùng thành phần liên thông với đỉnh v, bởi vì sau khi thăm đỉnh là lệnh gọi đến thủ tục DFS đối với tất cả các đỉnh kề với nó. Mặt khác, do mỗi khi thăm đỉnh v xong, biến Chuaxet[v] được đặt lại giá trị false nên mỗi đỉnh sẽ được thăm đúng một lần. Thuật toán lần lượt sẽ tiến hành tìm kiếm từ các đỉnh chưa được thăm, vì vậy, nó sẽ xét qua tất cả các đỉnh của đồ thị (không nhất thiết phải là liên thông). Để đánh giá độ phức tạp tính toán của thủ tục, trước hết nhận thấy rằng số phép toán cần thực hiện trong hai chu trình của thuật toán( hai vòng for của chương trình chính) là cỡ n. Thủ tục DFS phải thực hiện không quá n lần. Tổng số phép toán cần phải thực hiện trong các thủ tục này là O(n+m), do trong các thủ tục này ta phải xét qua tất cả các cạnh và các đỉnh của đồ thị. Vậy độ phức tạp tính toán của thuật toán là O(n+m).
Thí dụ 1. Xét đồ thị cho trong Hình 1. Các đỉnh của nó được đánh số lại theo thứ tự chúng được thăm theo thủ tục tìm kiếm theo chiều sâu mô tả ở trên. Giả thiết rằng các đỉnh trong danh sách kề của đỉnh v (Ke(v)) được sắp xếp theo thứ tự tăng dần của chỉ số.
8
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
3(9)
5(5)
2(2)
7(8)
8(6)
6(4)
1(1)
4(3)
9(7)
12(11)
13(10)
10(12)
11(13) Hình 1. Chỉ số mới (trong ngoặc) của các đỉnh được đánh lại theo thứ tự chúng được thăm trong thuật toán tìm kiếm theo chiều sâu
Thuật toán tìm kiếm theo chiều sâu trên đồ thị vô hướng trình bày ở trên dễ dàng có thể mô tả lại cho đồ thị có hướng. Trong trường hợp đồ thị có hướng, thủ tục DFS(v) sẽ cho phép thăm tất cả các đỉnh u nào mà từ v có đường đi đến u. Độ phức tạp tính toán là O(n+m). 1.2 Tìm kiếm theo chiều rộng trên đồ thị Để ý rằng trong thuật toán tìm kiếm theo chiều sâu đỉnh được thăm càng muộn sẽ càng sớm trở thành đã duyệt xong. Điều đó là hệ quả tất yếu của việc các đỉnh được thăm sẽ được kết nạp vào trong ngăn xếp (STACK). Tìm kiếm theo chiều rộng trên đồ thị, nếu nói một cách ngắn gọn, được xây dựng dựa trên cơ sở thay thế ngăn xếp (STACK) bởi hang đợi (QUEUE). Với sự cải biên như vậy, đỉnh được thăm càng sớm sẽ trở thành đã duyệt song (tức là càng sớm dời khỏi hang đợi). Một đỉnh trở thành đã duyệt xong ngay sau khi ta xét xong tất cả các đỉnh kề (chưa được thăm) với nó. Thủ tục có thể mô tả như sau:
Procedure BFS(v); (* Tìm kiếm theo chiều rộng bắt đầu từ đỉnh v; Các biến Chuaxet, Ke là biến toàn cục *)
begin QUEUE:= ; QUEUE:<= v; (* Kết nạp v vào QUEUE *) Chuaxet[v]:= false; While QUEUE do begin p <= QUEUE; (* Lấy p từ QUEUE *) Thăm_đỉnh(p); for u Ke(v) do
9
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
QUEUE <= u; Chuaxet[u]:= false; if Chuaxet[u] then begin end; end; end;
Khi đó, tìm kiếm theo chiều rộng trên đồ thị được thực hiện nhờ thuật toán
sau:
if Chuaxet[v] then BFS(v); (* Initialization *) for v V do Chuaxet[v]:= true; for v V do BEGIN END.
3(12)
5(9)
2(2)
7(6)
8(13)
6(5)
1(1)
4(3)
9(10)
12(4)
13(11)
Lập luận tương tự như trong thủ tục tìm kiếm theo chiều sâu, có thể chỉ ra được rằng lệnh gọi BFS(v) sẽ cho phép đến thăm tất cả các đỉnh thuộc cùng thành phần liên thông với đỉnh v, và mỗi đỉnh của đồ thị sẽ được thăm đúng một lần. Độ phức tạp tính toán của thuật toán là O(n+m). Thí dụ 2. Xét đồ thị trong Hình 2. Thứ tự thăm đỉnh của đồ thị này theo thuật
10(7)
toán tìm kiếm theo chiều rộng được ghi trong ngoặc.
11(8) Hình 2. Chỉ số mới (trong ngoặc) của các đỉnh được đánh lại theo thứ tự chúng được thăm trong thuật toán tìm kiếm theo chiều rộng
1.3 Tìm đường đi và kiểm tra tính liên thông Trong mục này ta xét ứng dụng các thuật toán tìm kiếm mô tả trong các mục trước vào việc giải bài toán cơ bản trên đồ thị: Bài toán tìm đường đi và bài toán về xác định các thành phần liên thông của đồ thị.
10
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Bài toán tìm đường đi giữa hai đỉnh Giả sử s và t là hai đỉnh nào đó của đồ thị. Hãy tìm đường đi từ s đến t.
Truoc[u]:=v; DFS(u); if Chuaxet[u] then begin end;
QUEUE u; Chuaxet[u]:= false; Truoc[u]:= p;
if Chuaxet[u] then begin end;
T p1:= Truoc[t] p2:= Truoc[p1] … s. Như trên đã phân tích, thủ tục DFS(s) (BFS(s)) sẽ cho phép thăm tất cả các đỉnh thuộc cùng một thành phần liên thông với s. Vì vậy, sau khi thực hiện xong thủ tục, nếu Chuaxet[t] = true, thì điều đó có nghĩa là không có đường đi từ s đến t, còn nếu Chuaxet[t] = false thì t thuộc cùng thành phần liên thông với s, hay nói một cách khác: Tồn tại đường đi từ s đến t. Trong trường hợp tồn tại đường đi, ta dùng thêm biến Truoc[v] để ghi nhận đỉnh đi trước đỉnh v trong đường đi tìm kiếm từ s đến v. Khi đó, đối với thủ tục DFS(v) cần sửa đổi câu lệnh if trong nó như sau: Còn đối với thủ tục BFS(v) cần sửa đổi câu lệnh câu lệnh if trong nó như sau: Đường đi cần tìm sẽ được khôi phục theo quy tắc sau:
Chú ý: Đường đi tìm được theo thuật toán tìm kiếm theo chiều rộng là đường đi ngắn nhất (theo số cạnh) từ đỉnh s đến đỉnh t. Điều này suy trực tiếp từ thứ tự thăm đỉnh theo thuật toán tìm kiếm theo chiều rộng.
,
)
( va i
1
v i
p 1 i
v0, v1,…, vp 2 Tìm đường đi ngắn nhất 2.1. Các khái niệm Trong phần này chúng ta chỉ xét đồ thị có hướng G = (V,E), |V| = n, |E| = m với các cung được gán trọng số, nghĩa là, mỗi cung (u,v) E của nó được đặt tương ứng với một số thực a(u,v) gọi là trọng số của nó. Chúng ta sẽ đặt a(u,v) = , nếu (u,v) E. Nếu dãy là một đường đi trên G, thì độ dài của nó được định nghĩa là tổng sau
11
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
d(s,t) = d(s,v) + a(v,t).
d[v] - khoảng cách từ đỉnh s đến tất cả các đỉnh còn lại v V; t - đỉnh đích; a[u,v], u, v V – ma trận trọng số trên các cung.
Mảng STACK chứa dãy đỉnh xác định đường đi nhắn nhất từ s đến t
Tức là, độ dài của đường đi chính là tổng các trọng số trên các cung của nó. (Chú ý rằng nếu chúng ta gán trọng số cho tất cả các cung đều bằng 1, thì ta thu được định nghĩa độ dài của đường đi như là số cung của đường đi giống như trong các phấn trước đã xét). Bài toán tìm đường đi ngắn nhất trên đồ thị dưới dạng tổng quát có thể phát biểu như sau: Tìm đường đi có độ dài nhỏ nhất từ một đỉnh xuất phát s V đến đỉnh cuối (đích) t V. Đường đi như vậy ta sẽ gọi là đường đi ngắn nhất từ s đến t còn độ dài của nó ta sẽ ký hiệu là d(s,t) và còn gọi là khoảng cách từ s đến t (khoảng cách định nghĩa như vậy có thể là số âm). Nếu như không tồn tại đường đi từ s đến t thì ta sẽ đặt d(s,t) = . Rõ ràng, nếu như mỗi chu trình trong đồ thị đều có độ dài dương, thì trong đường đi ngắn nhất không có đỉnh nào bị lặp lại (đường đi không có đỉnh lặp lại sẽ được gọi là đường đi cơ bản). Mặt khác, nếu trong đồ thị có chu trình với độ dài âm (chu trình như vậy, để ngắn gọn, ta sẽ gọi là chu trình âm) thì khoảng cách giữa một số cặp đỉnh nào đó của đồ thị có thể là không xác định, bởi vì, bằng cách đi vòng theo chu trình này một số đủ lớn lần, ta có thể chỉ ra đường đi giữa các đỉnh này có độ dài nhỏ hơn bất cứ một số thực cho trước nào. Trong những trường hợp như vậy, có thể đặt vấn đề tìm đường đi cơ bản ngắn nhất, tuy nhiên bài toán đặt ra sẽ trở nên phức tạp hơn rất nhiều. Trước hết cần chú ý rằng nếu biết khoảng cách từ s đến t, thì đường đi ngắn nhất từ s đến t, trong trường hợp trọng số không âm, có thể tìm được một cách dễ dàng. Để tìm đường đi, chỉ cần để ý là đối với cặp đỉnh s,t V tuỳ ý (s t) luôn tìm được đỉnh v sao cho Thực vậy, đỉnh v như vậy chính là đỉnh đi trước đỉnh t trong đường đi ngắn nhất từ s đến t. Tiếp theo ta lại có thể tìm được đỉnh u sao cho d(s,v) = d(s,u) + a(u,v),… Từ giả thiết về tính không âm của các trọng số dễ dàng suy ra rằng dãy t, v, u … không chứa đỉnh lặp lại và kết thúc ở đỉnh s. Rõ ràng dãy thu được xác định (nếu lật ngược thứ tự các đỉnh trong nó) đường đi ngắn nhất từ s đến t. Từ đó ta có thuật toán sau đây để tìm đường đi ngắn nhất từ s đến t khi biết độ dài của nó. Procedure Find_Path; (* Đầu vào: Đầu ra: *) begin STACK:=; STACK t; v:= t; While v s do begin u:= đỉnh thoả mãn d[v] = d[u] + a[u,v];
12
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
STACK u; v:= u;
end;
d[u] + a[u,v] < d[v] (1)
end; Chú ý rằng độ phức tạp tính toán của thuật toán là O(n2), do để tìm đỉnh u ta phải xét qua tất cả các đỉnh của đồ thị. Tất nhiên, ta cũng có thể sử dụng kỹ thuật ghi nhận đường đi trong phần trên: Dùng biến biến mảng Truoc[v], v V, để ghi nhớ đỉnh đi trước v trong đường đi tìm kiếm. Cần lưu ý thêm là trong trường hợp trọng số trên các cạnh là không âm, bài toán tìm đường đi ngắn nhất trên đồ thị vô hướng có thể dẫn về bài toán trên đồ thị có hướng, bằng cách thay mỗi cạnh của nó bởi hai cung có hướng ngược chiều nhau với cùng trọng số của các cạnh tương ứng. Tuy nhiên, trong trường hợp có trọng số âm việc thay như vậy có thể dẫn đến chu trình âm. 2.2 Thuật toán Ford – Bellman Phần lớn các thuật toán tìm khoảng cách giữa hai đỉnh s và t được xây dựng nhờ kỹ thuật tính toán mà ta có thể mô tả đại thể như sau: Từ ma trận trọng số a[u,v], u,v V, ta tính cận trên d[v] của khoảng cách từ s đến tất cả các đỉnh v V. Mỗi khi phát hiện cận trên d[v] sẽ được là tốt lên: d[v]:= d[u] + a[v]. Quá trình đó sẽ kết thúc khi nào chúng ta không làm tốt thêm bất cứ cận trên nào. Khi đó, rõ ràng giá trị của mỗi d[v] sẽ cho ta khoảng cách từ đỉnh s đến đỉnh v. Khi thể hiện kỹ thuật tính toán này trên máy tính, cận trên d[v] sẽ được gọi là nhãn của đỉnh v, còn việc tính lại các cận trên này sẽ gọi là phép gán nhãn cho đồ thị và toàn bộ thủ tục gọi là thủ tục gán nhãn. Nhận thấy rằng để tính khoảng cách từ s đến t, ở đây, ta phải tính khoảng cách từ s đến tất cả các đỉnh còn lại của đồ thị. Hiện nay vẫn chưa biết thuật toán nào cho phép tìm đường đi ngắn nhất giữa hai đỉnh làm việc thực sự hiệu quả hơn những thuật toán tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn lại. Sơ đồ tính toán mà ta vừa mô tả còn chưa xác định được, bởi vì còn phải chỉ ra thứ tự chọn các đỉnh u và v để kiểm tra điều kiện (1). Thứ tự chọn này có ảnh hưởng rất lớn đến hiệu quả của thuật toán. Bây giờ ta sẽ mô tả thuật toán Ford- Bellman tìm đường đi ngắn nhất từ đỉnh s đến tất cả các đỉnh còn lại của đồ thị. Thuật toán làm việc trong trường hợp trọng số của các cung là tuỳ ý, nhưng giả thiết rằng trong đồ thị không có chu trình âm. Procedure Ford_Bellman; (* Đầu vào: Đồ thị có hướng G = (V,E) với n đỉnh, s V là đỉnh xuất phát, a[u,v], u, v V, ma trận trọng số;
13
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
Truoc[v], v V, ghi nhận đỉnh đi trước v trong đường đi ngắn nhất từ s
d[v]:= a[s,v]; Truoc[v]:= s;
d[v]:= d[u] + a[u,v]; Truoc[v]:= u; for u V do if d[v] > d[u] + a[u,v] then begin end; (* Khởi tạo *) for v V do begin end; d[s]:= 0; for k:= 1 to n-2 do for v V \ {s} do
d[v]:= d[u] + a[u,v]; Truoc[v]:= u; if d[v] > d[u] + a[u,v] then begin end; for u Ke(v) do
Trong trường hợp này ta thu được thuật toán với độ phức tạp O(n.m) Giả thiết: Đồ thị không có chu trình âm. Đầu ra: Khoảng cách từ đỉnh s đến tất cả các đỉnh còn lại d[v], v V. đến v *) begin end; Tính đúng đắn của thuật toán có thể chứng minh trên cơ sở nguyên lý tối ưu của quy hoạch động. Rõ ràng là độ phức tạp tính toán của thuật toán là O(n3). Lưu ý rằng chúng ta có thể chấm dứt vòng lặp theo k thì phát hiện trong quá trình thực hiện hai vòng lặp trong không có biến d[v] nào bị đổi giá trị. Việc này có thể xảy ra đối với k < n-2, và điều đó làm tăng hiệu quả của thuật toán trong việc giải các bài toán thực tế. Tuy nhiên, cải tiến đó không thực sự cải thiện được đấnh giá độ phức tạp của bản thân thuật toán. Đối với đồ thị thưa tốt hơn là sử dụng danh sách kề Ke(v), v V, để biểu diễn đồ thị, khi đó vòng lặp theo u cần viết lại dưới dạng Thí dụ 1. Xét đồ thị cho trong hình 1. Các kết quả tính toán theo thuật toán
được mô tả trong bảng dưới đây.
14
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
(3)
(3)
(1)
(2)
(8)
(1)
5 3
(-5)
A = s=1
(3)
(4)
1 3 1 3 3 3 8 3 3 8 1 -5 1 -5 2 2 4 4
4 5
Hình 1. Minh hoạ cho thuật toán Ford-Bellman
k
1 2 3 d[1], Truoc[1] 0,1 0,1 0,1 0,1 d[2], Truoc[2] 1,1 1,1 1,1 1,1 d[3], Truoc[3] ,1 4,2 4,2 4,2 d[4], Truoc[4] ,1 4,2 3,5 3,5 d[5], Truoc[5] 3,1 -1,3 -1,3 -1,3
Bảng kết quả tính toán theo thuật toán Ford-Bellman
2.3 Thuật toán Dijkstra
Trong trường hợp trọng số trên các cung là không âm thuật toán do Dijkstra đề nghị để giải bài toán tìm đường đi ngắn nhất từ đỉng s đến các đỉnh còn lại của đồ thị làm việc hữu hiệu hơn rất nhiều so với thuật toán trình bày trong mục trước . thuật toán được xây dựng dừa trên cơ sở gán cho các đỉnh nhãn tạm thời . Nhãn của mỗi đỉnh cho biết cận trên của độ dài đường đi ngắn nhất từ s đến nó. Các nhãn này sẽ được biến đổi theo thủ tục lặp, mà ở đó mỗi bước lặp có một nhãn tạm thời trở thành nhãn cố định. Nếu nhãn của một đỉnh nào đó trở thành cố định thì nó sẽ cho ta không phải là cận trên mà là độ dài của đường đi ngắn nhất từ đỉnh s đến nó. Thuật toán được mô tả cụ thể như sau.
procedure Dijkstra; (* Đầu vào:đồ thị có hướng G=(V,E) với n đỉnh.
s V là đỉnh xuất phát, a[u,v],u.vV, ma trận trọng số;
Giả thiết : a[u,v] 0, u,v V . Đầu ra: Khoảng cách từ đỉnh s đến tất cả các đỉnh còn lại d[v] , vV.Truoc[v],
vV ghi nhận đỉnh đi trước v trong đường đi ngắn nhất từ s đến v*) Begin
(*khởi tạo*) for vV do begin
15
Generated by Foxit PDF Creator © Foxit Software http://www.foxitsoftware.com For evaluation only.
d[v]:= a[s,v]; truoc[v]= s;
end; d[s]:= 0; T:= V\{s}; (* T là tập đỉnh có nhãn tạm thời *)
d[v]:= d[u] + a[u,v]; Truoc[v]:= u;
end; (*bước lặp*) while T do begin Tìm đỉnh u T thoả mãn d[u] = min{d[z]:z T}; T:= T\{u}; (* Cố định nhãn của đỉnh u *) for v T do (* Gán lại nhãn cho các đỉnh trong T *) if d[v] > d[u] + a[u,v] then begin end;
end;
Định lý 1. Thoật toán Dijkstra tìm được đường đi ngắn nhất trên đồ thị sau
thời gian cỡ O(n2)
D(z) Chứng minh : Trước hết ta chứng minh là thuật toán tìm được đường đi ngắn
nhấttừ đỉnh s đến các đỉnh còn lại của đồ thị, Giả sử rằng ở một bước lặp nào đó các
nhãn cố định cho ta độ dài đường đi ngắn nhất từ s đến các đỉnh có nhãn cố định, ta
sẽ chứng minh ở lần lặp tiếp theo nếu đỉnh u* thu được nhãn cố định thì d(u*) chính
là độ dài đường đi ngắn nhất từ s đến u* .
Ký hiệu Sl là tập các đỉnh có nhãn cố định còn S2 là tập các đỉnh có nhãn tạm
thời ở bước lặp đang xét. Kết thúc mỗi bước lập tạm thời d[v] cho ta độ dài của
đường đi ngắn nhất từ s đến v qua những đỉnh nằm hoàn toàn trong S1 . Giả sử rằng
đường đi ngắn nhất từ s đến u* không nằm trong tập S1 . tức là nó đi qua ít nhất một
đỉnh của S2 . Gọi z S2 là đỉnh đầu tiên như vậy trong đường đi này. Do đó trọng số
trên các khung là không âm, nên đoạn đường từ z đến u* có độ dài L > 0 và
Bất đẳng thức này là mâu thuẫn với cách xác định đỉnh u* là đỉnh có nhãn tạm thời
nhỏ nhất. vậy đường đi ngắn nhất từ s đến u* phải nằm trọn trong S1 và thế d[u* ] là
độ dài của nó. Do ở lần lặp đậu tiên S1= {s} và sau mỗi lần lặp tạo thêm vào S1 một
đỉnh u* nên giả thiết d(v) cho độ dài đường đi ngắn nhất s đến v với mọi v S1 là
đúng với bước lặp đậu tiên. Theo qui nạp suy ra thuật toán cho ta đường đi ngắn nhất
từ s đến đỉnh của đồ thị .
Bây giờ sẽ đánh gía số phép toán cần thưc hiện theo thuật toán . Ở mỗi bước
lặp lại để tìm ra đỉnh u cần phải thực hiện O(n) phép toán. Và để gán nhãn lại cũng
cần phải thực hiện một số lượng phép toán cũng là O(n). Thuật toán phải thực hiện n
-1 bước lặp, vập thời gian tính toán của phép toán là cỡ O(n2). 16 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Định lý được chứng minh.
Khi đã tìm được độ dài của đường đi ngắn nhất d[v] thì đường đi này có thể (7) tìm dựa vào nhãn Truoc[v], v V, theo quy tắc giống như chúng ta đã xét trước. Thí dụ 2. Tìm đường đi ngắn nhất từ đỉnh 1 đến các đỉnh còn lại của đồ thị ở (5) (1) (2) (1) (2) (4) (2) 3 2 2 (3) 1 2 2 Hình 2. Hình 2. Minh hoạ thuật toán Dijkstra Kết quả tín toán theo thuật toán được trình bày trong thuật toán dưới đây. Qui
ước viết hai thành phần của nhãn theo thứ tự: d[v], Truoc[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 -. 1,1*
-
-
-
-
- ,1
3,2*
-
-
-
- ,1
8,2
8,2
5,3*
-
- ,1
,1
7,4
7,4
6,6*
- 0,1
-
-
-
-
- Bước lặp Đỉnh 1 Đỉnh 2 Đỉnh 3 Đỉnh 4 Đỉnh 5 Đỉnh 6
Khởi tạo
,1
6,2
1
4,4*
2
-
3
4
-
-
5
Bảng kết quả tính toán theo thuật toán Dijkstra (14) Thí dụ 3. Tìm đường đi ngắn nhất từ đỉnh 1 đến tất cả các đỉnh còn lại trong 6 2 3 đồ thị vô hướng sau. (15) (11) (16) (20) (18) 17 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Hình 3. Minh hoạ thuật toán Dijkstra
cho đồ thị vô hướng Bước lặp Đỉnh 1 Đỉnh 2 Đỉnh 3 Đỉnh 4 Đỉnh 5 Đỉnh 6
Khởi tạo
.1
24.2
1
24.2*
2
-
3
-
4
-
5 11.1*
-
-
-
-
- 12.1
12.1*
-
-
-
- .1
.1
31.4
31.4*
-
- .1
.1
.1
41.3
41.3*
- 0.1
-
-
-
-
- Bảng kết quả tính toán theo thuật toán Dijkstra Chú ý:
1) Nếu chỉ cần tìm đường đi ngắn nhất từ s đến một đỉnh t nào đó thì có thể kết thúc thuật toán khi có đỉnh t trở thành nhãn cố định.
2) Tương tự như mục 2, dễ dàng mô tả lại thuật toán cho trường hợp đồ thị
cho bởi danh sách kề. Để có thể giảm bớt khối lượng tính toán trong việc xác định
đỉnh u ở mỗi bước lặp. Khi đó có thể thu được thuật toán với độ phức tạp tính toán là
O(m logn). Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Nhiều bài toán quy hoạch tuyến tính có thể quy về bài toán làm cực tiểu phí
tổn vận chuyển hàng trong một mạng (gồm các nút và các cung đường) sao cho đảm
bảo được các nhu cầu ở một số nút khi đã biết nguồng cung cấp tại một số nút khác.
Các bài toán như vậy được gọi là các bài toán luồng trên mạng (network flow
problem) hoặc bài toán chuyển vận (transshipment problem). Đây là lớp bài toán
quan trọng nhất và hay gặp nhất trong quy hoạch tuyến tính. Lớp này bao gồm các
bài toán quen thuộc trong thực tế như: bài toán vận tải, các bài toán mạng điện và
mạng giao thông, các bài toán quản lý và phân bổ vật tư, bài toán bổ nhiệm, bài toán
kế hoạch tài chính, bài toán đường ngắn nhất, bài toán luồng cực đại … Bài toán luồng cực đại trong mạng là một trong số những bài toán tối ưu trên
đồ thị tìm được những ứng dụng rộng rãi trong thực tế cũng như những ứng dụng thú
vị trong lý thuyết tổ hợp. Bài toán được đề xuất vào đầu những năm 1950, và gắn liền
với tên tuổi của hai nhà bác học Mỹ là Ford và Fulkerson. Trong chương này chúng
ta sẽ trình bày thuật toán của Ford và Fulkerson để giải bài toán đặt ra và nêu một số
ứng dụng của bài toán.
I. PHÁT BIỂU BÀI TOÁN
1.Mạng. Luồng trong mạng Để thuận tiện cho việc trình bày ta sẽ quy ước rằng nếu không có cung (v,w) Đị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.
thì khả năng thông qua c(v,w) được gán bằng 0. Đị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 ≤ 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 v
)( Div 0 ) f wvf
,(
)
v
w
w ( ( )(v )(v vf
)(
)
v
- tập các đỉnh của mạng mà từ đó có cung đến v, cung đi vào đỉnh v bằng tổng luồng trên các cung đi ra khỏi đỉnh v, nếu v s,t: - tập các đỉnh E v
)( ,(: ) E
vwVw
),
,
wvVw . v
)(
(:
3.Giá trị của luồng f là số
val ( ) f ) .), wsf
,(
)(
s twf
(
)(
t
w
w Trong đó
của mạng mà từ v có cung đến nó:
19 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 2. 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. * Bài toán như vậy có thể xuất hiện trong rất nhiều ứng dụng thực tế . chẳng hạn
khi cần xác định cường độ lớn nhất của dòng vận tải giữa 2 nút của một bản đồ giao
thông. Trong ví dụ này của bài toán luồng cực đại xẽ chỉ cho ta các đoạn đường đông
xe nhất và chúng tạo thành “chỗ hẹp” tương ứng với dòng giao thỗng xét theo hai nút
được chọn. Mộtví dụ khác là nếu xét đồ thị tương ứng với một hệ thống dẫn dầu.
Trong đó các ống tương ứng với các cung , điểm phát có thể có thể là tàu chở dầu,
điểm thu là bể chứa, còn những điểm nối giữa các ống là các nút của đồ thị. Khả
năng thông qua của các cung tường ứng với tiết diện các ống.Cần phải tìn luộng dầu
lớn nhất có thể bơm từ dầu vào bể chứa.
3. Lát cắt. Đường tăng luồng . Định lý Ford- Fulkerson wv
, X ). c ( ) , Định nghĩa 3. Ta gọi lát cắt (X,X*) là một cách phân hoạch tập đỉnh V của
mạng ra thành hai tập X và X*=V \ X , trong đó s X và t X* . Khả năng thông
qua của lát cắt (X,X*) là số
Xc
( *
v
w X
X Lát cắt với khả năng thông qua nhỏ nhất được gọi là lát cắt hẹp nhất. Bổ đề 1. giá trị của mọi luồng f trong mạng luôn nhỏ hơn bằng khả năng thông qua lát cắt (X,X*) bất kỳ trong nó : val(f) c(X,X*). , ( ) )) val vwf ) ( f ) ( v
w
(
Xv
w ,(
wvf
)
(
v
Tổng này sẽ gồm các số hạng dạng f(u,v) với dấu cộng hoặc dấu trừ mà trong
đó có ít nhất một trong hai đỉnh u, v phải thuộc tập X. Nếu cả hai đỉnh u, v đều trong
tập X, thì f(u,v) xuất hiện với dấu cộng trong Divf(v) và có dấu trừ trong Divf(u). Vì
thế, chúng triệt tiêu lẫn nhau. Do đó, sau khi giản ước các số hạng như vậy ở vế trái,
ta thu được
wv
, wv
, val ,) ( ) ( ) ( f f f * *
X
X
v
w
X
X
v
w Chứng minh. Cộng các điều kiện cân bằng luồng Divf(v) = 0 với mọi v X. Khi đó ta có val ( f ) f ( wv
, ) ( wv
, ). f
* *
Xv
Xw
Xv
Xw
hay là 20 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. f ( wv
, ) c ( wv
, ). * *
X
X
v
w
X
X v
w
Mặt khác từ điều kiện 1 rõ ràng là ( wv
, ) 0 f
*
v
X
w
X
còn suy ra val(f) c(X,X*). Bổ đề được chứng minh.
Từ bổ đề 1 suy ra Hệ quả 1. Giá trị luồng cực đại trong mạng không vượt quá khả năng thông qua của lát cắt hẹp nhất trong mạng.
Ford và Fulkerson đã chứng minh rằng giá trị luồng cực đại trong mạng đúng
bằng khả năng thông qua của lát cắt hẹp nhất. Để có thể phát biểu và chứng minh kết
quả này chúng ta sẽ cần thêm một số khái niệm.
Giả sử f là một luồng trong mạng G = (V,E). Từ mạng G = (V,E) ta xây dựng
đồ thị có trọng số trên cung Gf =(V,Ef) , với tập cung Ef và trọng số trên các cung
được xác định theo quy tắc sau: 10 Nếu e = (v,w) E với f(v,w) = 0, thì (v,w) Ef với trọng số c(v,w);
20 Nếu e = (v,w) E với f(v,w) = c(v,w), thì (w,v) Ef với trọng số
f(v,w);
30 Nếu e = (v,w) E với 0 s s 4,1 3 3,3 1 b cung còn lại gọi là cung nghịch. Đồ thị Gf được gọi là đồ thị tăng luồng. Thí dụ: Các số viết cạnh các cung của G ở hình 1 theo thứ tự là khả năng c c 1 b thông qua và luồng trên cung.
3 1 2 3,0 1 3 3,2 2,2 e d e 21 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Hình 1. Mạng G và luồng f. Đồ thị có trọng số Gf tương ứng. Giả sử P = (s = v0,v1,v2,… ,vk= t) là một đường đi từ s đến t trên đồ thị tăng
luồng Gf . Gọi là giá trị nhỏ nhất của các trọng số của các cung trên đường đi P .
Xây dựng luồng f ‘ trên mạng G theo quy tắc sau: f(u,v) + , nếu (u,v) P là cung thuận
f ‘(u,v) = f(u,v) - , nếu (u,v) P là cung nghịch
f(u,v), nếu (u,v) P Dễ dàng kiểm tra được rằng f‘ được xây dựng như trên là luồng trong mạng và
val(f ‘)= val(f) + . Ta sẽ gọi thủ tục biến đổi luồng vừa nêu là tăng luồng dọc theo
đường P. Định nghĩa 4. Ta gọi đường tăng luồng f là mọi đường đi từ s đến t trên đồ thị tăng luồng G(f). wv
, wv
, wv
, ). ( ) ( ) ) ( ( f f f f * * *
v
X
Xw
v
X
Xw
v
X
Xw
Định lý 1. Các mệnh đề dưới đây là tương đương:
(i) f là luồng cực đại trong mạng:
(ii) Không tìm được đường tăng luồng f:
(iii) val(f) = c(X,X*) với mọi lát cắt (X,X*) nào đó.
Chứng minh.
(i) => (ii). Giả sử ngược lại, tìm được đường tăng luồng P. Khi đó ta có thể
tăng giá trị luồng bằng cách tăng luồng dọc theo đường P. Điều đó mâu thuẫn với
tính luồng cực đại của luồng f.
(ii) => (iii). Giả sử không tìm được đường tăng luồng. Ký hiệu X là tập tất cả
các đỉnh s trong đó đồ thị Gf, và đặt X* = V\X. Khi đó (X,X*) là lát cắt, và f(v,w)=0 với
mọi v X*, w X nên
val
Với vX, wX*. do (v, w) Gf , nên f(v, w) = c(v, w). Vậy 22 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. , f ) ( ( ) ( ) ( val wvc
, wvf
, XXc * ). *
Xv
Xw * Định lý 1 là cơ sở xây dựng thuật toán lặp sau đây để tìm luồng cực đại trong
mạng: Bắt đầu từ luồng với luồng trên tất cả các cung bằng 0 ( ta sẽ gọi luồng như
vậy là luồng không ), và lặp lại bước lặp sau đây cho đến khi thu được luồng mà đối
với nó không còn luồng tăng: Thuật toán Ford – Fulkerson 10 Xuất phát từ một luồng chấp nhận được f.
20 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 30 Nếu (P) = + thuật toán kết thúc. có, tiếp bước 3 dưới đây.
Trong đó (P) - Lượng luồng tăng thêm, hay nói khác là làm sự tăng luồng (flow
augmentation) dọc theo đường đi tăng luồng P một lượng thích hợp mà các ràng buộc
của bài toán vẫn thoả. Cách tìm đường đi tăng luồng. Ta sử dụng thuật toán gán nhãn có nội dung
như sau. Một đường đi P thoả mãn về đường đi tăng luồng, nhưng chỉ đi từ s đến k
nào đó (chưa tới t, nói chung) sẽ được gọi là đường đi chưa bão hoà (unsaturated
path).
Ta nói đỉnh u là đã đánh dấu (u is labeled) nếu ta biết là có một đường đi chưa
bão hoà từ s tới u. Bây giờ ta sẽ xét tất cả các đỉnh v có nối trực tiếp đến đỉnh u (sẽ
gọi là ở cạnh đỉnh u) xem chúng có thể được gán nhãn hay không khi u đã gán nhãn.
Việc này được gọi là thăm (scanning) đỉnh u. Nếu (u,v) có luồng trên cung F(u,v) < C(u,v) thì ta có thể nối thêm cung (u,v)
và đường đi chưa bão hoà P từ s đến u để được đường đi chưa bão hoà tới v. Vậy v có
thể gán nhãn.
Bước lặp tăng luồng ( Ford - Fulkerson): Tìm dường tăng P đối với luồng hiện có. Tăng luồng dọc theo đường P. Khi đã có luồng cực đại, lát cắt hẹp nhất có thể tìm theo thủ tục mô tả trong
chứng minh định lý 1. Sơ đồ của thuật toán Ford – Fulkerson có thể mô tả trong thủ
tục sau đây: Procedure Max_Flow; 23 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. (* Thuật toán Ford – Fulkerson *)
begin (* Khởi tạo: Bắt đầu từ luồng với giá trị 0 *)
for u V do for v V do f(u,v):=0; Stop:=false;
While not Stop do
if< Tìm được đường tăng luồng P> then end; Để tìm đường tăng luồng trong Gf có thể sử dụng thuật toán tìm kiếm theo
chiều rộng ( hay thuật toán tìm kiếm theo chiều sâu) bắt đầu từ đỉnh s, trong đó
không cần xây dựng tường minh đồ thị Gf. Ford- Fulkerson đề nghị thuật toán gán
nhãn chi tiết sau đây để giải bài toán luồng trong mạng. Thuật toán bắt đầu từ luồng
chấp nhận được nào đó trong mạng ( có thể bắt đầu từ luồng không) sau đó ta sẽ tăng
luồng bằng cách tìm các đường tăng luồng. Để tìm đường tăng luồng ta sẽ áp dụng
phương pháp gán nhãn cho các đỉnh. Mỗi đỉnh trong quá trình thực hiện thuật toán sẽ
ở một trong ba trạng thái: chưa có nhãn, có nhãn chưa xét, có nhãn đã xét. Nhãn của
một đỉnh v gồm 2 phần và có một trong hai dạng sau: [+p(v), (v)] hoặc [-p(v), (v)
]. Phần thứ nhất +p(v) (-p(v)) chỉ ra là cần tăng (giảm) luồng theo cung (p(v),v) cung
(v,p(v)) còn phần thứ hai (v) chỉ ra lượng lớn nhất có thể tăng hoặc giảm theo cung
này. Đầu tiên chỉ có đỉnh s được khởi tạo nhãn và nhãn của nó là chưa xét, còn tất cả
các đỉnh còn lại đều chưa có nhãn . Từ s ta gán cho tất cả các đỉnh kề với nó và nhãn
của đỉnh s sẽ trở thành nhãn đã xét. Tiếp theo, từ mỗi đỉnh v có nhãn chưa xét ta lại
gán nhãn cho tất cả các nhãn chưa có nhãn kề với nó và nhãn của đỉnh v trở thành
nhãn đã xét. Quá trình sẽ được lặp lại cho đến khi hoặc là đỉnh t trở thành có nhãn
hoặc là nhãn của tất cả các đỉnh có nhãn đều là đã xét nhưng đỉnh t vẫn chưa có nhãn.
Trong trường hợp thứ nhất ta tìm được đường tăng luồng, còn trong trường hợp thứ
hai đối với luồng đang xét không tồn tại đường tăng luồng ( tức là luồng đã là cực đại
). Mỗi khi tìm được đường tăng luồng, ta lại tăng luồng theo đường tìm được, sau đó
xoá tất cả các nhãn và đối với luồng mới thu được lại sử dụng phép gán nhãn các
đỉnh để tìm đường tăng luồng. Thuật toán sẽ kết thúc khi nào đối với luồng đang có
trong mạng không tìm được đường tăng luồng. Thuật toán gán nhãn (The labeling algorithm) Gọi VT là tập mọi đỉnh đã gán nhãn nhưng chưa được thăm. Ta có thuật toán Xuất phát với VT = {s} và s là nút đã đánh dấu duy nhất. để tìm đường đi tăng luồng.
Một bước lặp sẽ có VT hiện hành và gồm ba bước như sau. 24 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 20 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 30 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 10 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).
v vào tập VT.
tập VT.
Bây giờ ta xét kết quả của thuật toán gán nhãn. Nó có kết thúc hữu hạn hay
không? Nhận xét rằng một đỉnh được vào tập VT chỉ khi chuyển từ chưa gán nhãn.
Do đó một đỉnh chỉ được vào VT nhiều nhất là một lần. Mà mỗi bước lặp bỏ một đỉnh
ra khỏi VT. Do đó, vì số đỉnh của mạng là hữu hạn, thuật toán phải kết thúc hữu hạn. 6,4 6,5 5,4 3,1 d b 3,0 6,1 5,2 1,1 t s c e Thí dụ 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 đỉnh của mạng G với luồng f được cho như Hình 1, hai số viết bên cạnh
mỗi cung là khả năng thông qua và luồng của các cung. Kết quả các bước của thuật
toán mô tả bởi các đồ thị và bảng dưới đây. Mạng với luồng cực đại thu được ở Hình
2. Lát cắt bé nhất là X = {s,c}, X* = {b,d,e,t} và giá trị luồng cực đại là 9. Hình 1 6,4 6,5 5,4 3,1 d(b+,1) b(s+,1) 3,0 6,1 t(d+,1) 5,2 1,1 s
(s,) c(s+,3) e(b+,1) 6,5 6,6 5,5 3,1 d b 3,0 6,1 5,2 1,1 t s c e + Bước lặp 1: s b d t, 1 = 1 25 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 6,6 5,5 3,3 d b 3,2 6,3 5,4 1,1 t s c e 6,5 6,6 5,5 3,1 d(c+,2) b(d-,2) 3,0 6,1 t(e+,2) 5,2 1,1 s
(-,) c(s+,3) e(b+,2) 6,3 6,6 5,5 3,3 d b 3,2 6,3 5,4 t + Bước lặp 2: s c d b e t, 2 = 2
6,3
+ Bước lặp 3: Không còn đường tăng luồng, Val(fmax) = 5+4 = 9 s c e 1,1
Hình 2. Mạng G với luồng cực đại và lát cắt hẹp nhất e b c d t s+,1 S+,3 b+,1 b+,1 d-,2 S+,3
S+,1 c+,2 b+,2 d+,1
e+,2 Đường
tăng luồng
sbd t
scdbet Giá trị tăng
luồng
1
2 Lặp Đỉnh
xét
s
b
c
d
s
c
d
b
e
s 1
2
3 Bảng kết quả của thuật toán Ford-Fullkerson 26 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Thí dụ 2. Á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: 7,0 6,0 5,0 4,0 4,0 4,0 a b 5,0 3,0 12,0 7,0 9,0 s c t e d 7,0 6,0 5,0 4,0 4,0 b(a+,6) t(e+,2) 5,0 4,0
c(s+,4)
3,0 12,0 7,0 9,0 s
(s,) e(d+,4) d(s+,7) 7,4 6,4 5,0 4,4 4,0 4,0 a b 5,0 3,0 s c t 12,0 7,0 9,0 + Bước lặp 1: s a b t, 1 = 1
a(s+,6) e d 7,4 6,4 5,0 4,4 4,0 + Bước lặp 2: s a b c e t, 2 = 2 a(s+,2) b(a+,2) t(e+,2) 5,0 4,0
c(b+,2)
3,0 12,0 7,0 9,0 s
(s,) e(c+,2) d(s+,7) 7,6 6,6 5,0 4,4 4,2 4,0 b a 3,2 5,0 12,2 7,0 9,0 c s t e d 27 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 7,6 6,6 5,0 4,4 4,0 a(s+,0) b(a+,1) t(e+,1) 5,0 4,2
c(s+,4)
3,2 12,2 7,0 9,0 s
(s,) e(c+,1) d(s+,7) + Bước lặp 3: s c e t, 3 = 1 7,6 6,6 5,0 4,4 4,2 4,1 b a 5,0 3,3 12,3 7,0 9,0 c t s e d + Bước lặp 4: s d e t, 4 = 7 7,6 6,6 5,0 4,4 4,1 a(s+,0) b(a+,1) t(e+,7) 5,0 4,2
c(s+,3)
3,3 12,3 7,0 9,0 s
(s,) e(d+,7) d(s+,7) 7,6 6,6 5,0 4,4 4,2 4,1 a b 5,0 3,3 12,10 7,7 9,7 c t s e d + Bước lặp 5: s c d e t, 5 = 2 7,6 6,6 5,0 4,4 4,1 a(s+,0) b(a+,1) t(e+,2) 5,0 4,2
c(s+,3)
3,3 12,10 7,7 9,7 s
(s,) e(d+,2) d(c+,3) 28 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 7,6 6,6 5,0 4,4 4,2 4,3 b a 5,2 3,3 12,12 7,7 9,9 s t c e d + Bước lặp 6: Không còn đường tăng luồng nữa, Val(fmax) = 6+3+7 = 16. 29 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Begin Mạng với luồng zero Stop:= False Tăng luồng True True not Stop Find_Path Path-Found False False Stop:= False Mạng với luồng
cực đại End Sơ đồ thuật toán Ford-Fullkerson tổng quát 30 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Begin P[t]:= s ; [t]:= +
VT = V\{s} PathFound:= True False VT True u VT; For vV\VT False C[u,v] >0 and (F[u,v] True P[v]:= u; [v]:=min{[u],C[u,v]-F[u,v]}
VT:= VT {v} True End v= t False False C[v,u]>0 and
F[v,u]>0 True P[v]:= -u; [v]:= min{[u],F[v,u]}
VT:= VT {v} Sơ thuật toán Find_Path (Chi tiết) { Trả về TRUE nếu có đường tăng luồng } 31 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. True v= t End PathFound:= False End False 32 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Begin v:= P[t] ; u:= t ; tang:= [t] False End u s True False True f[v,u]:=f[v,u] + tang v:= -v v > 0 Sơ đồ thuật toán tăng luồng (Inc_Flow)
{ Tăng luồng nếu có đường tăng } u:=v; v:=P[u] f[v,u]:=f[v,u] - tang 33 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Hai thủ tục Tìm đường tăng luồng và Tăng luồng có thể mô tả bởi chương trình như sau. If v=t then exit; if (c[u,v]>0) and (f[u,v]< c[u,v]) then
begin
p[v]:= u;
[v]:= min { [u],c[u,v] – f[u,v]};
VT = VT {v}; (* Nạp v vào danh sách đỉnh có nhãn *)
end;
if (c[v,u]>0) and (f[v,u]>0) then
begin
p[v]:= -u;
[v]:= min {[u],f[v,u]};
VT = VT {v}; (* Nạp v vào danh sách đỉnh có nhãn *)
If v=t then exit;
end; u<= VT; (* Lấy u từ VT *)
for v V\VT do
begin
end;
PathFound:= false; p[s]:=s;
[s]:= +;
VT= V\{s};
PathFound:=true;
While VT do
Begin
end; Procedure Find_Path;
(* thủ tục gán nhãn tìm đường tăng luồng
p[v], [v] là nhãn của đỉnh v;
VT – danh sách các đỉnh nhưng chưa xét;
c[u,v]- khả năng thông qua của cung (u,v),u,v V;
f[u,v]- luồng trên cung (u,v),(u,v V ) *)
begin
procedure Inc_Flow;
(* Tăng luồng theo đường tăng *)
begin v:=p[t]; u:=t; tang:= [t];
while u s do
begin if v>0 then f[v,u]:= f[v,u] + tang; 34 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. v:= -v;
f[u,v]:= f[u,v] – tang; else
begin
end;
u:= v; v:= p[u]; end; Find_Path;
If PathFound then Inc_Flow
Else Stop:=true; (* Khởi tạo: Bắt đầu từ luồng với giá trị 0 *)
for u V do
for v V do f[u,v]:=0;
Stop:=false;
While not Stop do
begin
end;
< Luồng cực đại trong mạng là f[u,v],u,v V >
< Lát cắt hẹp nhất là (VT, V\VT) > end;
Thuật toán Ford- Fulkerson được thực hiện nhờ thủ tục:
Procedure Max_Flow;
(* Thuật toán Ford- Fulkerson *)
begin
end;
Giả sử khả năng thông qua của tất cả các cung của đồ thị là các số nguyên. Khi đó
sau mỗi lần tăng luồng, giá trị luồng sẽ tăng lên ít nhất là 1. Từ đó suy ra thuật toán
Ford- Fulkerson sẽ dừng không quá val(f*) lần tăng luồng và cho ta luồng cực đại
trong mạng. Đồng thời, rõ ràng f*(u,v) sẽ là số nguyên đối với mỗi cung (u,v) E. Từ
đó ta có kết quả sau: Định lý 2 (Định lý về luồng cực đại trong mạng và lát cắt hẹp nhất). Luồng cực đại trong mạng bằng khả năng thông qua của lát cắt hẹp nhất. Định lý 3. (Định lý về tính nguyên). Nếu tất cả các khả năng thông qua là
các số nguyên thì luôn tìm được luồng cực đại với luồng trên các cung là các số
nguyên.
Tuy nhiên, nếu các khả năng thông qua là các số rất lớn thì giá trị luồng cực
đại cũng có thể là rất lớn và khi đó thuật toán mô tả ở trên sẽ đòi hỏi rất nhiều bước
tăng luồng. Thí dụ trong hình 2 sẽ minh hoạ cho điều này. Hình 2(a) mô tả mạng cần
xét với khả năng thông qua trên các cung. Hình 2(b) mô tả luồng trên các cung (số 35 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. s s s 106,1 106 106,1 106 106,0 106,1 1,0 1,1 1 a a a b b b 106 106,1 106,0 106 106,1 106,1 t t t (b) (c) (a) thứ hai bên cạnh cung ) sau khi thực hiện tăng luồng dọc theo đường tăng luồng
(s,a,b,t). Hình 2(c) mô tả luồng trên các cung sau khi thực hiện tăng luồng dọc theo
đường tăng luồng (s,b,a,t). Rõ ràng, sau 2.106 lần tăng luồng theo đường (s,b,a,t) và
(s,b,a,t) một cách luân phiên ta thu được luồng cực đại. Hình 2. Ví dụ tồi tệ với thuật toán Ford- Fulkerson. Hơn thế nữa nếu các khả năng thông qua là các số vô tỷ, người ta còn xây
dựng được ví dụ để cho thuật toán không dừng, và tệ hơn là dãy các giá trị luồng xây
dựng theo thuật toán hội tụ thì nó còn không hội tụ đến giá trị luồng cực đại. Như
vậy, muốn thuật toán làm việc hiệu quả, việc lựa chọn đường tăng luồng cần được
tiến hành hết sức cẩn thận.
Edmonds và Karp chỉ ra rằng nếu đường tăng luồng được chọn là đường ngắn
nhất từ s đến t trên đồ thị Gf . Điều đó có thể thực hiện, nếu trong thủ tục tìm đường
tăng Find_Path mô tả ở trên, danh sách VT được tổ chức dưới dạng QUEUE ( nghĩa
là ta thực hiện tìm đường tăng bởi thủ tục tìm kiếm theo chiều rộng) thì thuật toán sẽ
kết thúc sau không quá mn/2 lần sử dụng đường tăng luồng. Nếu để ý rằng, tìm kiếm
theo chiều rộng trên đồ thị đòi hỏi thời gian O(n+m), thì thuật toán thu được sẽ có độ
phức tạp tính toán là O(nm2).
Nhờ cách tổ chức tìm đường tăng khéo léo hơn, người ta đã xây dựng được
thuật toán với độ phức tạp tính toán tốt hơn như: O(n2m) (Dinic, 1970), O(n3)
(Karzanov, 1974), O(n2m1/2) ( Cherkasky, 1977), O(nm log n) (Sleator- Tarjan,1980).
II. BÀI TOÁN LUỒNG CỰC ĐẠI VỚI KHẢ NĂNG THÔNG QUA CÁC CUNG – CÁC
ĐỈNH
1.Bài toán Giả xử trong đồ thị G = (V,E), ngoài khả năng thông qua của các cung c(u,v),
ở mỗi đỉnh v V còn có khả năng thông qua của đỉnh là d(v), và đòi hỏi tổng luồng
đi vào đỉnh v không còn vượt quá d(v), tức là 36 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. vwf ( , ) )(
vd
Vw
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 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 Cần phải tìm luồng cực đại giữa s và t trong mạng như vậy.
Xây dựng một mạng G’ sao cho: mỗi đỉnh v của G tương ứng với hai đỉnh v+,
v- trong G’, mỗi cung (u,v) trong G ứng với cung (u,v+) trong G’, mỗi cung (v,w)
trong G ứng với cung (v-,w+) trong G’. Ngoài ra, mỗi cung (v+,v-) trong G’ có khả
năng thông qua là d(v), tức là bằng khả năng thông qua của đỉnh v trong G.
2. Giải quyết bài toán
theo hai bước sau:
thông qua cung. Thí dụ 1. C[u,t] C[s,u] u du (a) C[u,v] C[s,v] C[v,t] t dt s
ds v dv C[u,t] C[s,u] u+ u- du (b) C[u,v] C[v,t] C[s,v] t+ t- dt s+ s- ds v+ v- dv
Hình 1. Hình 1a cho ví dụ mạng G với khả năng thông qua ở cung và đỉnh.
Hình 1b là mạng G’ tương ứng chỉ có khả năng thông qua ở các cung. Do luồng đi vào đỉnh v+ phải đi qua cung (v+,v-) với khả năng thông qua d(v),
nên luồng cực đại trong G’ sẽ bằng luồng cực đại trong G với khả năng thông qua
của các cung và đỉnh. 37 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Thí dụ 2. Xác định mạng G’ từ mạng G được cho như sau: 5 4 u[6] 1 2 3 s[7] t[6] v[8] Hình 2. Mạng G với khả năng thông qua các cung và đỉnh 6 u- u- 5 4 t+ t- s+ s- 7 6 2 8 1 3 v+ v- Hình 3. Mạng G’ tương ứng với khả năng thông qua các cung. 3. Một số bài toán tối ưu tổ hợp ứng dụng từ bài toán luồng Bài toán luồng cực đại có rất nhiều ứng dụng trong việc giải nhiều bài toán tổ
hợp. Khó khăn chính ở đây là phải xây dựng tương ứng sao cho việc tìm luồng cực
đại trong nó sẽ tương đương với việc giải bài toán đặt ra. Mục này sẽ giới thiệu một
số bài toán như vậy.
3.1. Bài toán đám cưới vùng quê Có m chàng trai ở một làng quê nọ. Đối với mỗi chàng trai ta biết các cô gái
mà anh ta vừa ý. Hỏi khi nào thì có thể tổ chức các đám cưới trong đó chàng trai nào
cũng sánh duyên với cô gái mà mình vừa ý.
Ta có thể xây dựng đồ thị với các đỉnh biểu thị các chàng trai và các cô gái,
còn các cung biểu thị sự vừa ý của các chàng trai đối với các cô gái. Khi đó ta thu
được một đồ thị hai phía. Thí dụ. Có 4 chàng trai {T1,T2,T3,T4} và 5 cô gái {G1,G2,G3,G4,G5}. Sự vừa ý cho trong bảng sau 38 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Chàng trai
T1
T2
T3
T4 Các cô gái mà chàng trai ưng ý
G1, G4, G5
G2
G2, G3, G4
G2, G4 G1 T1 T2 G2 Đồ thị tương ứng được cho trong hình 7. G3 T3 T4 G4 t s Hình 7. Mạng tương ứng với Bài toán đám cưới vùng quê Đưa vào điểm phát s và điểm thu t. Nối s với tất cả các đỉnh biểu thị các chàng
trai, và nối t với tất cả các đỉnh biểu thị các cô gái. Tất cả các cung của đồ thị đều có
khả năng tông qua bằng 1. Bắt đầu từ luồng 0, ta tìm luồng cực đại trong mạng xây
dựng được theo thuật toán Ford- Fulkerson. Từ định lý về tính nguyên, luồng trên các
cung là các số 0 hoặc 1. Rõ ràng là nếu luồng cực đại trong đồ thị có giá trị Vmax = m,
thì bài toán có lời giải, và các cung với luồng bằng 1 sẽ chỉ ra cách tổ chức đám cưới
thoả mãn điều kiện đặt ra. Ngược lại, nếu bài toán có lời giải thì Vmax=m. bài toán về
các đám cưới vùng quê là một trường hợp riêng của bài toán về cặp ghép trên đồ thị
hai phía mà để giải nó có thể xây dựng thuật toán hiệu quả hơn.
3.2. Bài toán về hệ thống đại diện chung Cho tập m phần tử X = {z1,z2,…,zm} Giả sử V x ,..., u 2 m
v
,..., 2
xx
,
1
uu
,
1
,
y
,...,
ts
,
vv
,
1 2 m ,...,
n
yy
,
1 n 2 Xây dựng mạng G=(V,E) với tập đỉnh 39 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. i
1, 1, n z j
i A
i
n :)
z
i 1, 1, với
mj
mj
(
1:), .
n
1:
E
xs
,
i
n
i
mj
v
y
1:)
(
,
vu
(
,
i ty
i B
i j i j j Trong đó đỉnh xi tương ứng với tập Ai đỉnh yi tương ứng với đỉnh Bi ,các phần tử ui,vi
tưong ứng với phần tử zj . Tập các cung mạng của G được xác định như sau
,
(
ux
i
j
với
:) Khả năng thông qua của tất cả các cung được đặt bằng 1. Dễ dàng thấy rằng
hệ thống đại diện chung của hai dãy , x ,..., x ) min Trong mục này ta sẽ trình bày thuật toán được xây dựng dựa trên thuật toán
tìm luồng cực đại để giải một bài toán tối ưu rời rạc là mô hình toán học cho một số
bài toán tối ưu tổ hợp. Xét bài toán tối ưu rời rạc (
xf
1 2 n ij max
1 mi n
x
1
j
(1) , , i p m ,..., 2,1 với điều kiện i ij xa
ij 1 (2) Bài toán (1)-(3) là mô hình toán học cho nhiều bài toán tối ưu tổ hợp thực tế. Có m sinh viên và n nhóm sinh hoạt chuyên đề. Với mỗi sinh viên i, biết Đưa vào biến số
xij =1, nếu sinh viên i tham gia vào nhóm j,
xij =0, nếu ngược lại, aij =1, nếu sinh viên có i nguyện vọng tham gia vào nhóm j,
aij =0, nếu ngược lại,
và pi là số lượng nhóm chuyên đề mà họ có nguyện vọng tham gia và đảm bảo mỗi
sinh viên i phải tham gia đúng pi nhóm, hãy tìm cách phân phối với số người trong
nhóm có nhiều sinh viên tham gia nhất là nhỏ nhất có thể được.
i=1,2,…,m, j= 1,2,…,n, khi đó dễ thấy mô hình toán học cho bài toán đặt ra chính là
bài toán (1)-(3): Xét bài toán tối ưu rời rạc 40 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. , x ,..., x ) min (
xf
1 2 n ij max
1 mi n
x
1
j
(1) , , i p m ,..., 2,1 với điều kiện i ij xa
ij 1 (2) Đưa vào biến số
xij = 1, nếu bố trí tiểu ban i làm việc ở phòng j,
xij =0, nếu ngược lại, , x ,..., x ) min Một hội nghị có m tiểu ban, mỗi tiểu ban cần sinh hoạt trong một ngày tại
phòng họp phù hợp với nó. Có n phòng họp dành cho việc sinh hoạt của các tiểu ban.
Biết
aij =1, nếu phòng họp i là thích hợp với tiểu ban j,
aij =0, nếu ngược lại,
i=1,2,…,m; j=1,2,…,n. Hãy bố trí các phòng họp sao cho hội nghị kết thúc sau ít
ngày làm việc nhất.
i=1,2,…,m,j=1,2,…,n, khi đó dễ thấy mô hình toán học cho bài toán đặt ra chính là
bài toán (1)-(3): Xét bài toán tối ưu rời rạc n ij (
xf
1 2 mi max
1 n
x
j
1
(1) p 2,1 ,..., m i , , với điều kiện ij xa
ij i 1 (2) a p , i 2,1 ,..., m . Bổ đề 2. Bài toán (1)-(3) có phương án tối ưu khi và chỉ khi ij i 1 n
j (4) I+i = {1 j n: aij = 1}, Chứng minh. Điều kiện cần của bổ đề là hiển nhiên vì sự tồn tại phương án
của bài toán suy ra các bất đẳng thức trong (4) được thực hiện ít nhất dưới dạng dấu
đẳng thức. Để chứng minh điều kiện đủ, chỉ cần chỉ ra rằng nếu điều kiện (4) được
thực hiện thì bài toán luôn có phương án. Thực vậy, giả sử điều kiện (4) được thực
hiện. Khi đó nếu ký hiệu
thì | I+i | pi , i=1,2,…,m. Do đó nếu gọi 41 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. ij)mxn với các thành phần được xác đinh theo công thức Ii I+i , | Ii | = pi , i=1,2,…,m, ij =0, j Ii , i=1,2,…,m, (5) ij =1, j Ii , x* x* thì X* = (x*
Là phương án của bài toán (1)-(3). Bổ đề được chứng minh. 2,1 2,1 ,..., ,..., m V n j i : t
i Do (4) là điều kiện cần để bài toán (1)-(3) có phương án, nên trong phần tiếp jm
; ,..., ,..., ,..., i E :) 2,1 2,1 2,1
( j wu
,
i
n j 2,1 ,..., i
:),
(
us
,(
tw
j theo ta sẽ luôn giả thiết rằng điều kiện này được thực hiện.
Bây giờ ta sẽ chỉ ra rằng việc giải bài toán (1)-(3) có thể dẫn về việc giải một
số hữu hạn bài toán luồng cực đại trong mạng. Trước hết, với mỗi số nguyên dương
k, xây dựng mạng G(k) = (V,E) với tập đỉnh
s
u
w
:
j
trong đó s là điểm phát, t là điểm thu, và tập cung
i
:) q(s,ui) = pi , i = 1,2,…,m,
q(ui,wj) = aij , i = 1,2,…,m; j = 1,2,…,n;
q(wj,t) = k, j = 1,2,…,n. k pi
m
.
n
mỗi cung e E được gán với khả năng thông qua q(e) theo qui tắc sau:
Hình 8 chỉ ra cách xây dựng mạng G(k). s t ui q(ui,wj)=aij
wj m ip i 1
Hình 8. Mạng G(k). Ký hiệu:
Bổ đề sau đây cho thấy mối liên hệ giữa luồng cực đại trong mạng G(k) và phương
án của bài toán (1)-(3). Bổ đề 3. Giả xử đối với số nguyên dương k nào đó, luồng cực đại nguyên *
ij)mxn với các thành phần được xác trong mạng G(k) có giá trị là . Khi đó X* = (x*
định theo công thức. ij = *(ui,wj), i=1,2,…,m; j=1,2,…,n. x* là phương án của bài toán (1)-(3). 42 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Chứng minh. Thực vậy, do luồng cực đại trong mạng có giá trị là và luồng * ij x ,(
us ) *
,(
us ) 2,1 ,..., m . i i ,
ip
i n
1
j n
*
1
j *(s,ui) = pi, i= 1,2,…,m,
*(ui,wj) {0,1}, i= 1,2,…,m; j=1,2,…,n, nguyên nên
từ đó suy ra Vậy X* là phương án của bài toán (1)-(3). Bổ đề được chứng minh. ij) là phương án tối ưu của k* và là giá trị tối ưu của bài Bổ đề 4. Giả sử X*(x* * theo công thức sau toán (1)-(3) khi đó luồng cực đại trong mạng G(k*) có giá trị . * * * ij ,(
us ) p , ( ) x , i i ,
wu
i j * * ij ( x , i 2,1 ,..., ;
jm 2,1 ,..., n . ),
tw
j m
1
i
* là luồng trong mạng G(m) có giá trị là . Bổ đề được Chứng minh. Do giá trị của luồng cực đại trong mạng G(k*) không vượt quá
nên để chứng minh bổ đề ta chỉ cần chỉ ra luồng giá trị trong mạng G(k*).Xây
dựng luồng Dễ dàng kiểm tra được rằng
chứng minh. Bổ đề 5 . Nếu k=m thì luồng cực đại trong mạng G(m) có giá tị là Chứng minh. Lập luận tương tự như trong bổ đề 4, ta chỉ cần chỉ ra luồng với
giá trị trong mạng G(m) . Thực vậy,giả sử X*=(x*ịj)mxn là phương án của bài toán
* theo công thức giống như
(1)-(3) xây dựng theo công thức 5. Xây dựng luồng
trong chứng minh bổ đề 4, ta có luồng với giá trị . Bổ đề được chứng minh.
Từ bổ đề 3 và 4 suy ra việc giải bài toán (1)-(3) dẫn về việc tìm giá trị k*
nguyên dương nhỏ nhất sao cho luồng cực đại trong mạng G(k*) có giá trị .Bổ đề 5
cho thấy giá trị k*[1,m]. Vì vậy để giải bài toán (1)-(3) ta có thể áp dụng phương
pháp tìm kiếm nhị phân trên đoạn [1,m] để tìm giá trị k*, trong đó ở mỗi bước cần
giải một bài toán luồng cực đại. Để giải bài toán tìm luồng cực đại trong mạng, có thể
sử dụng thuật toán đa thức như đã nói ở trên. Từ đó suy ra kết quả sau Định lý 5. Bài toán (1)-(3) giải được nhờ thuật toán đa thức với độ phức tạp
tính toán của bài toán là log2m . ONF trong đó ONF là độ phức tạp tính toán của bài
toán tìm luồng cực đại trong mạng G(k) Thí dụ 3. Bài toán phân nhóm sinh hoạt Giả sử có m sinh viên SV1, SV2,.., SVm và n nhóm sinh hoạt N1, N2,.., Nn. 43 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. i ( n a ), A ,1 ,1 ij . . n 1 2 1 N
1
0 N
0
1 2 A N
1
0
.
.
1 0 1 SV
SV
.
.
SV m ,
jm
là ma trận đăng ký sinh hoạt theo nguyện vọng của sinh viên.
với aij = 1 nếu SVi đăng ký nhóm Nj , aij = 0 nếu ngược lại
Gọi P ( ), i ,1 m P
i 1 1 2 2 p N P , i SV
SV
.
. P
P
.
. SV P m m Gọi ,
jm ,1 ,1 B n b ( i ),
ij
Với bij = 1 nếu SVi đăng ký Nj , bij = 0 nếu ngược lại. Sao cho: n b ,1 m ,
iP
i ij j 1 là ma trận chứa số lượng từng chuyên đề mà SVi phải tham gia đúng Pi , i = 1..m
chuyên đề.
Bài toán đặt ra là xác định ma trận n min, j ,1 n ij
b i 1 Và - Rõ ràng, ma trận A với tổng các phần tử trên hàng i là khả năng thông qua của đỉnh i. - Điều kiện tối ưu của bài toán là tìm cách phân phối số người trong nhóm có - Khả năng thông qua cung (i,j) là 1 nghĩa là SVi có đăng ký nguyện vọng sinh
hoạt nhóm Nj. Giá trị luồng của cung này có thể là 1 hoặc 0 (SVi không được sinh
hoạt nhóm Nj).
nhiều SV tham gia nhỏ nhất chính là khả năng thông qua các cung vào đỉnh t.
- Để giải quyết bài này, ta áp dụng Bổ đề 3 bằng cách cho khả năng thông qua
các cung này bằng k và tìm luồng cực đại của mạng này. Đầu tiên, xét k = 1,2,...,m.
Và áp dụng Bổ đề 4 để xác định k* với luồng cực đại tương ứng. 44 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Thí dụ 4 Xét bài toán với m = 3(SV) và n = 4 nhóm sinh hoạt A 2 P 3 3 1011
1001
1110
Ma trận chỉ tiêu đăng ký chuyên đề
Ma trận đăng ký sinh hoạt B 1110 0011
1001
Hình sau là mạng với luồng cực đại biểu diễn phân nhóm sinh hoạt. Trong đó
khả năng thông qua của các đỉnh SVi chính là khả năng thông qua của các cung
(S,SVi) và bằng : m a ; i ,1 n ij 1 j k n ,1
,1 Khi đó ma trận kết quả phân nhóm tối ưu SV1 N1 1 2 1 N2 2 2 1 SV2 t Khả năng thông qua của các cung (Ni,t) là
,
im 1 S 2 N3 1 1 3 1 2 SV3 1 N4
Khả năng thông qua của các cung (SVi,Nj) là 1, (i = 1..n, j = 1..m) 0 Hình 1. Mạng với luồng cực đại biểu diễn phân công sinh hoạt chuyên đề 45 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. I. PHÂN TÍCH BÀI TOÁN
1. Mô hình bài toán vwf )(
vd ) ,
Vw
Giả xử trong đồ thị G, ngoài khả năng thông qua của các cung c(u,v), ở mỗi
đỉnh v V còn có khả năng thông qua của đỉnh là d(v), và đòi hỏi tổng luồng đi vào
đỉnh v không còn vượt quá d(v), tức là
( Từ mạng G = (V,E) với khả năng thông qua các cung các đỉnh. Ta tìm luồng Cần phải tìm luồng cực đại giữa s và t trong mạng như vậy.
Xây dựng một mạng G’ sao cho: mỗi đỉnh v của G tương ứng với hai đỉnh v+,
v- trong G’, mỗi cung (u,v) trong G ứng với cung (u,v+) trong G’, mỗi cung (v,w)
trong G ứng với cung (v-,w+) trong G’. Ngoài ra, mỗi cung (v+,v-) trong G’ có khả
năng thông qua là d(v), tức là bằng khả năng thông qua của đỉnh v trong G.
2. Phương pháp giải quyết
cực đại của mạng qua hai bước sau:
Bước 1: Xác định mạng G’.
Bước 2: 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.
Hai bước trên ta có thể biểu diễn dưới dạng sơ đồ thuật toán sau: 46 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Begin Mạng G Mạng G’ Luồng cực đại trên G’ End Giả sử mạng G = (V,E), |V| = n. Ta có thể biểu diễn bởi ma trận trọng số A cấp A = ( aij ) = di nếu i = j
c[i,j] nếu [i,j] E
0 nếu [i,j] E 3. Biểu diễn đồ thị
3.1 Biểu diễn mạng G với khả năng thông qua các cung - đỉnh
n x n như sau:
Trong đó: di là khả năng thông qua đỉnh i; C[i,j] khả năng thông qua cung [i,j].
3.2 Biểu diễn mạng G’ tương ứng với mạng G Mạng tương ứng với G = (V,E), |V | = n là mạng G’ = (V’,E’), |V’| = 2 |V |, nếu i = j A’ = ( a’ij ) = 0
c[i,j] nếu [i,j] E’ |E’| = 2 |E | - 1. Được biểu diễn thông qua ma trận A’ cấp (2n x 2n) như sau: 47 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Thí dụ 3. Như thí dụ trên có mạng G như sau: 4 5 u[6] 1 3 2 s[7] t[6] A = v[8] s u v t
7 5 2 0 s
0 6 1 4 u
0 0 8 3 v
0 0 0 6 t 6 u- u- 5 4 t+ t- s+ s- 7 6 1 2 8 3 A’ = v+ v- s+ s- u+ u- v+ v- t+ t-
0 7 0 0 0 0 0 0 s+
0 0 5 0 2 0 0 0 s-
0 0 0 6 0 0 0 0 u+
0 0 0 0 1 0 4 0 u-
0 0 0 0 0 8 0 0 v+
0 0 0 0 0 0 3 0 v-
0 0 0 0 0 0 0 6 t+
0 0 0 0 0 0 0 0 t- Ta có ma trận biểu diễn mạng G :
Tương tự từ mạng G’:
Ta có ma trận biểu diễn mạng G’ như sau: 48 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. C = Áp dụng T.T Ford-Fulkerson tìm luồng cực đại cho mạng G’ ta được mạng s+ s- u+ u- v+ v- t+ t-
0 6 0 0 0 0 0 0 s+
0 0 4 0 2 0 0 0 s-
0 0 0 4 0 0 0 0 u+
0 0 0 0 0 0 4 0 u-
0 0 0 0 0 2 0 0 v+
0 0 0 0 0 0 2 0 v-
0 0 0 0 0 0 0 6 t+
0 0 0 0 0 0 0 0 t- Với Val(f*) = 6 49 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. snc:=snc+1;
for i:=1 to Ssv do
kt[i]:=kt[i]+C^[i,j];
end;
function Ok:boolean;
var ktra:boolean;
kt:array[1..max] of integer;
r,i,j:word;
begin
readfile;
sum_ei;
ktra:=false;
for i:=1 to ssv do
begin
r:=0;
for j:=1 to sn do
r:= r+C^[i,j];
if r < kt[i] then begin
ktra:=false;
exit;
end
else ktra:=true;
end;
Ok:=ktra;
end;}
(*==============================================*)
function min(a,b:integer):integer;
begin
if a>b then min:=b else min:=a;
end;
(*==========================================*)
function EmptyVt:word;
var
i:word;
begin
EmptyVt:=0;
for i:=1 to N do
if Vt[i]=1 then
begin
EmptyVt:=i;
exit;
end;
end; 50 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. (*================================================*)
{Tìm đường đi để tăng luồng}
procedure find_path;
begin
fillchar(Vt,sizeof(vt),0);
ee[sw]:=INF;
p[sw]:=sw;
Vt[sw]:=1;
pathfound:=true;
while EmptyVt<>0 do
begin
u:=EmptyVt;
Vt[u]:=2;
for v:=1 to n do
if (Vt[v]=0) and(u<>v) then
begin
if (C^[u,v]>0) and (f^[u,v] 51 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. f^[u,v]:=f^[u,v]-ee[t];
end;
u:=v;v:=p[u];
end;
end;
(*==========================================*)
{thuật toán tăng luồng toàn bộ để tìm luồng cực đại}
procedure Max_flow;
var
stop:boolean;
begin
for u:=1 to N do
for v:=1 to N do f^[u,v]:=0;
stop:=false;
while not stop do
begin
Find_path;
if pathfound then inc_flow
else stop:=true;
end;
end;
(*======================================================*)
{Chuyển Ma trận cho dưới dạng quan hệ thành ma trận để thực hiện luồng cực đại
input : C[i,j] là quan hệ hàng i và cột j c[i,j]=1 else c[i,j]:=0;
Sn:so cột
Ssv:so hàng
e[i]:so bat buoc cua hàng i
}
procedure TransMatrixFlow;
var
i,j:word;
begin
N:=Sn+Ssv+2;
sw:=1;
t:=N;
for i:=1 to Ssv do
for j:=1 to Sn do F^[i,j]:=c^[i,j];
fillchar(c^,sizeof(c^),0);
{gan them diem cuoi den tat ca cac nhom co luong vo cung}
for j:=1 to Ssv do C^[1,j+1]:=e[j];
for j:=1 to Sn do
for i:=1 to Ssv do
C^[i+1,Ssv+j+1]:=F^[i,j];
{gan them diem dau den tat ca cac SV co luong vo cung}
for i:=1 to Sn do 52 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. begin
C^[Ssv+i+1,N]:=INF;
end;
end;
(*===================================================*)
{đổi 2 nhóm sao cho chênh lệch là bé nhất}
procedure changegroup(n1,n2:word);
var
c1,i,j,k1,k2:word;
begin
if F^[Ssv+1,n1]=F^[Ssv+1,n2] then exit;
if F^[Ssv+1,n1]>F^[Ssv+1,n2] then begin k1:=n1;k2:=n2;end
else
begin
k1:=n2;
k2:=n1;
end;
for c1:=1 to Ssv do
if (F^[Ssv+1,k1]>F^[Ssv+1,k2]) and (c1<=Ssv)
and (F^[c1,k1]=1)and (C^[c1,k2]=1) and (F^[c1,k2]=0) then
begin
F^[c1,k1]:=0;F^[c1,k2]:=1;
dec(F^[Ssv+1,k1]);
inc(F^[Ssv+1,k2]);
inc(c1);
end;
end;
(*==============================================*)
procedure TransresultM;
var
t,i,j:word;
begin
for i:=1 to Ssv do
begin
for j:=1 to Sn do
begin
F^[i,j]:=F^[i+1,Ssv+j+1];
C^[i,j]:=C^[i+1,Ssv+j+1];
end;
F^[i,Sn+1]:=e[i];
end;
{tinh so SV trong nhom}
for j:=1 to Sn do
begin
t:=0; 53 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. for i:=1 to Ssv do t:=t+F^[i,j];
F^[Ssv+1,j]:=t;
end;
for i:=1 to Sn do
for j:=1 to Sn do
if i<>j then changeGroup(i,j);
end;
(*================================================*)
procedure init;
begin
clrscr;
new(C);
if c=nil then writeln('Khong du bo nho');
new(F);
if F=nil then writeln('Khong du bo nho');
end;
(*===============================================*)
procedure finish;
begin
if c<>nil then dispose(C);
if F<>nil then dispose(F);
end;
procedure writexy(x,y:integer;clr:byte;s:string);
begin
gotoxy(x,y);
textattr:=clr;
write(s);
end;
(*===================================================*)
(* copy ký tự ch, tại vị trí thứ j ,trong chuỗi s*)
function cpystr(s:string;ch:char;j:byte):string;
var
ie,i,is:byte;
nn,nl:byte;
begin
nn:=0;
cpystr:='';
nl:=length(s);
i:=1;
while (i<=nl) and (nn<>j) do
begin
if s[i]=ch then nn:=nn+1;
inc(i);
end; 54 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. if i 55 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. cmd :word;
xs :array[1..NUMPOPUP] of byte;
luuscreen:^byte;
begin
xs[1]:=2;
index:=1;
getmem(luuscreen,80*25*2);
if luuscreen=nil then exit;
for i:=2 to NUMPOPUP do
xs[i]:=xs[i-1]+length(cpystr(MenuBarStr,'/',i))+2;
window(1,1,80,1);
textattr:=clr; {const MenuBarStr:string='/File / Exe / Help /';}
clrscr;
for i:=1 to NUMPOPUP do
writexy(xs[i],1,clr,cpystr(MenuBarStr,'/',i));
if opt=0 then exit;
move(ptr($B800,0)^,luuscreen^,80*25*2);
repeat
window(1,1,80,1);
textattr:=clr;
writexy(xs[index],1,clrsel,cpystr(MenuBarStr,'/',index));
cmd:=popupmenu(xs[index],2,20,popupnum[index],mnupopup[index],clrsel,clr);
if (cmd=$80) or (cmd=$81) then Move(luuscreen^,ptr($B800,0)^,80*25*2);
{ function Ptr(Seg, Ofs: Word): Pointer;
Converts a segment base and an offset address to a
pointer-type value.}
{procedure Move(var Source, Dest; Count: Word);Copies bytes
from source to dest.}
if (cmd=$80) then
if (index>1) then dec(index) else index:=NUMPOPUP;
if (cmd=$81) then
if (index 56 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. clrscr;
write(s);
end;
(*=================================================*)
procedure message(s:string);
begin
drawwindow(20,5,60,7,$21,$21,2);
write(s);
readln;
end;
(*==================================================*)
function inputbox(tilte:string):string;
var
s:string;
begin
drawwindow(20,10,60,13,$21,$21,2);
write(tilte);
drawwindow(25,12,55,12,$7F,$1F,0);
readln(s);
inputbox:=s;
end;
(*=============================================*)
procedure repaint;
begin
{ window(1,1,80,25);}
clrscr;
textattr:=$00;
window(1,25,80,25);
writestatus(' F10');
writexy( 3,23,$70,' Show Menu'); {(*$70:dat mau cho statusbar*)}
menubar($70,$70,0); {dat mau cho toolbar}
drawwindow(1,2,80,24,$1f,$1F,0);
{(*$1f,$1f mau nen:3bit cao, mau chu :4 bit thap*)}
end;
(*=========================================================*)
(* CAC THU TUC TUONG UNG VOI CAC MENU *)
(*=========================================================*)
function FileExit(filename:ss):boolean;
var f:text;
begin
{$I-}
assign(f,filename);
reset(f);
close(f);
{$I+} 57 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. FileExit:=(Ioresult=0)and(filename<>'');
end;
{-------------------------------------------------------------------------------------}
procedure savefile;
var
i,j:word;
begin
repaint;
fileinput:=inputbox('Nhap Duong dan va ten File:');
assign(ff,fileinput);
{$I-}
rewrite(ff);
{$I+}
if IOresult<>0 then message('File khong hop le hoac sai duong dan')
else
begin
for i:=1 to ssv+1 do
begin
for j:=1 to sn do write(ff,F^[i,j]:5);
writeln(ff,e[i]:5);
end;
close(ff);
end;
end;
(* ============================================= *)
procedure openfile;
var i,j:byte;
begin
repaint;
fileinput:=inputbox('Nhap Duong dan va ten File :');
assign(ff,fileinput);
{$I-}
reset(ff);
{$I+}
if IOresult<>0 then message('File khong ton tai hoac sai duong dan')
else
begin
readfile;
close(ff);
end;
repaint;
drawwindow(1,2,79,24,$1F,$1F,2);
writeln('Ma tran dang ky :');
writeln;
for i:=1 to Ssv do 58 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. begin
for j:=1 to Sn do write(C^[i,j]:3);writeln;
end;
writeln;
for i:=1 to Ssv do
begin
gotoxy(25,i+2);
writeln(e[i]);
end;
gotoxy(22,1);write('Chi tieu :');
readln;
end;
(*-----------------------------------------------------------------------------------*)
procedure newfile;
var
f:string;
j,i,cn,m:word;
key:char;
begin
REPAINT;
drawwindow(1,2,79,24,$1F,$1F,2);
write('Nhap So hang <= 200 : ');readln(ssv);
write('Nhap So cot <= 100 : ');readln(sn);
writeln('CHU Y !');
writeln('1. Hang i quan he cot j thi C[i,j] = 1, nguoc lai C[i,j]= 0.');
writeln('2. Nhap Du Lieu chi gom cac so 0 hoac 1.');
writeln('3. Neu ban nhap sai ban phai nhap lai .');
writeln('4. Cho den khi thoa man dieu kien de bai.');
for i:=1 to ssv do
begin
for j:=1 to sn do
begin
repeat
write('C[',i,',',j,']:=');
readln(C^[i,j]);
until C^[i,j] in [0,1];
end;
repeat
write('Nhap so nhom ma hang ',i,' Phai tham gia: P',i,' = ');
readln(e[i]);
if e[i] > sn then
begin
writeln('Nhap sai !, Nhap lai .'); 59 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. writeln('So nhom phai tham gia P',i,' <= ',sn,' (So ban vua nhap)');
end;
until e[i] <= sn;
end;
repaint;
f:=inputbox('Nhap Duong dan va ten File:');
assign(ff,f);
{$I-}
rewrite(ff);
{$I+}
if IOresult<>0 then message('File khong hop le hoac sai duong dan')
else
begin
writeln(ff,ssv,' ',sn);
for i:=1 to ssv do
begin
for j:=1 to sn do write(ff,C^[i,j],' ');
writeln(ff,e[i]);
end;
close(ff);
end;
end;
(******************************************************************)
(* CHUAN BI MO PHONG *)
(******************************************************************)
procedure xuat;
begin
setcolor(9);
settextstyle(1,0,1);
settextjustify(2,8);
outtextxy(460,405,' GVHD : DO NHU AN ');
outtextxy(438,428,' SVTH : Ngo Tao Vinh ' );
outtextxy(438,446,' LOP : Tin 40 DHTS ');
end;
(*----------------------------------------------------------------------*)
procedure display;
begin
setfillstyle(1,7);
bar(1,0,getmaxx,24);
setfillstyle(1,8);(* mau nen*)
bar(1,25,getmaxx,getmaxy-100);
setcolor(9); 60 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Bar(1,25,getmaxx,getmaxy);
setcolor(2); (*set color chu *)
bar(1,getmaxy-90,getmaxx,getmaxy);
setcolor(2);
settextstyle(1,0,2);
settextjustify(1,1);
outtextxy(160,450,'Phan Nhom Sinh hoat ');
outtextxy(170,420,'Ford - Fulkerson Algorithms');
xuat;
setcolor(15);
line(1,getmaxy-92,getmaxx,getmaxy-92);
line(1,getmaxy-91,getmaxx,getmaxy-91);
line(321,25,321,getmaxy-92);
line(321,26,321,getmaxy-93);
line(1,22,getmaxx,22);
line(1,23,getmaxx,23);
end;
(*------------------------------------------------------------------------*)
procedure vechu(x,y:integer;st:string;mau,co,cl,jus:word);
begin
setcolor(cl);
settextjustify(jus,1);
settextstyle(mau,0,co);
outtextxy(x,y,st);
end;
{-----------------------------------------------------------------------}
{thu tuc ve khung voi ca c toa do (x1,y1) x2,y2 voi mau cl}
procedure khung(x1,y1,x2,y2,cl:integer);
begin
setcolor(cl);
line(x1,y1,x2,y1);
line(x1,y1,x1,y2);
line(x1,y2,x2,y2);
line(x2,y1,x2,y2);
end;
(*=====================================================*)
procedure vechu1;
var i,j:byte;
begin
settextstyle(0,1,0);
setcolor(15);
outtextxy(15,140,'Sinh Vien Dang Ky');
setcolor(14); 61 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. line(21,80,21,215);
line(16,210,21,215);
line(26,210,21,215);
setcolor(15);
settextstyle(0,0,0);
outtextxy(80,80,'Nhom Dang Ky');
setcolor(14);
line(40,90,190,90);
line(185,85,190,90);
line(185,95,190,90);
for j:=1 to sn do
begin
for i:=1 to ssv do
begin
str(C^[i,j],s);
setcolor(15);
settextstyle(0,0,1);
outtextxy(21*j+7,14*i+85,s);
end;
end;
{j:=sn+1;}
for i:=1 to ssv do
begin
str(e[i],s);
setcolor(15);
settextstyle(0,0,1);
outtextxy(210,14*i+85,s);
setcolor(15);
settextstyle(0,0,0);
outtextxy(190,80,'Chi Tieu');
end;
(* Viet ma tran ket qua *)
{ setcolor(15);
settextstyle(0,1,0);
outtextxy(getmaxx div 2+15,80,'Sinh Vien Duoc PN');
setcolor(14);
line(getmaxx div 2+25,90,30,21,((getmaxY-44) div 2)+165);}
{ line(getmaxx div 2+21,((getmaxY-44) div 2)+30,21,((getmaxY-44) div 2)+165);
line(getmaxx div 2+16,((getmaxY-44) div 2)+160,21,((getmaxY-44) div 2)+165);
line(getmaxx div 2+26,((getmaxY-44) div 2)+160,21,((getmaxY-44) div 2)+165);
setcolor(15);
settextstyle(0,0,0); 62 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. outtextxy(40,((getmaxY-44) div 2)+30,'Nhom Dang Ky');
setcolor(14);
line(40,((getmaxY-44) div 2)+40,190,((getmaxY-44) div 2)+40);
line(185,((getmaxY-44) div 2)+35,190,((getmaxY-44) div 2)+40);
line(185,((getmaxY-44) div 2)+45,190,((getmaxY-44) div 2)+40);}
for j:=1 to sn do
begin
for i:=1 to ssv do
begin
str(F^[i,j],s);
setcolor(15);
{outtextxy(21*j+7,14*i+(getmaxY-44) div 2+40,s);}
outtextxy(getmaxx div 2+25+21*j+7,14*i+85,s);
end;
end;
{setcolor(15);
outtextxy(100,70,'Ma Tran Dang Ky');
outtextxy(100,240,'Ma Tran Ket Qua');}
{ for i:=1 to ssv do
begin
for j:=1 to sn do
begin
str(C^[j,i],s);
setcolor(15);
outtextxy(20*i+ssv,20*j+(sn+1)+70,s);
end;
end;}
end;
(*------------------------------------------------------------------------*)
procedure toado1;
var i,j,k:integer;
x11,y11,x22,y22:integer;
tdotrai,tdophai,qqq,tdoy,temp,sogia:word;
begin
setcolor(15);
tdotrai:=15;tdophai:=getmaxx div 2-15;
tdoy:=getmaxy div 2;
i:=1;k:=1;qqq:=1;
while (qqq<=ssv+sn) do
begin
if temp<6 then sogia:=100 else sogia:=50;
toado[i].x:=30+tdotrai+50; 63 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. toado[i].y:=sogia+50*qqq;
toadoo[k].x:=30+tdophai-100;
toadoo[k].y:=sogia+50*qqq;
i:=i+1;k:=k+1;qqq:=qqq+1;
end;
for i:=1 to ssv do
begin
x11:=toado[i].x;
y11:=toado[i].y;
setcolor(4);
circle(x11,y11,7);
circle(x11,y11,6);
setfillstyle(1,15);
floodfill(x11,y11,4);
setcolor(3);
settextstyle(0,0,0);
outtextxy(x11,y11-15,chr(48+i));
setcolor(4);
line(tdotrai,tdoy,toado[i].x,toado[i].y);
end;
for k:=1 to sn do
begin
x22:=toadoo[k].x;
y22:=toadoo[k].y;
setcolor(4);
circle(x22,y22,7);
circle(x22,y22,6);
setfillstyle(1,15);
floodfill(x22,y22,4);
setcolor(3);
settextstyle(0,0,0);
outtextxy(x22,y22-15,chr(48+k));
setcolor(4);
line(tdophai,tdoy,toadoo[k].x,toadoo[k].y);
end;
setcolor(4);
circle(tdotrai,tdoy,7);
circle(tdotrai,tdoy,6);
setfillstyle(1,15);
floodfill(tdotrai,tdoy,4);
setcolor(3);
settextstyle(0,0,0); 64 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. settextjustify(tdotrai,tdoy);
outtextxy(tdotrai,tdoy-15,'s');
setcolor(4);
circle(tdophai,tdoy,7);
circle(tdophai,tdoy,6);
setfillstyle(1,15);
floodfill(tdophai,tdoy,4);
setcolor(3);
settextstyle(0,0,0);
settextjustify(tdophai,tdoy);
outtextxy(tdophai,tdoy-15,'t');
for i:=1 to ssv do
begin
for j:=1 to sn do
if C^[i,j]=1 then
begin
setcolor(4);
line(toado[i].x,toado[i].y,toadoo[j].x,toadoo[j].y);
end;
end;
end;
(*========================================================*)
procedure toado2;
var i,j,k,m,x11,y11,x22,y22:integer;
tdotrai,tdophai,qqq,tdoy,temp,sogia:word;
begin
setcolor(15);
tdotrai:=getmaxx div 2+15;tdophai:=getmaxx -15;
tdoy:=getmaxy div 2;
i:=1;k:=1;qqq:=1;
while (qqq<=ssv+sn) do
begin
if temp<6 then sogia:=100 else sogia:=50;
toado[i].x:=30+tdotrai+50;
toado[i].y:=sogia+50*qqq;
toadoo[k].x:=30+tdophai-80;;
toadoo[k].y:=sogia+50*qqq;
i:=i+1;k:=k+1;qqq:=qqq+1;
end;
for i:=1 to ssv do
begin 65 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. x11:=toado[i].x;
y11:=toado[i].y;
setcolor(4);
circle(x11,y11,7);
circle(x11,y11,6);
setfillstyle(1,15);
floodfill(x11,y11,4);
setcolor(3);
settextstyle(0,0,0);
settextjustify(100,100);
outtextxy(x11,y11-15,chr(48+i));
setcolor(4);
line(tdotrai,tdoy,toado[i].x,toado[i].y);
end;
for k:=1 to sn do
begin
x22:=toadoo[k].x;
y22:=toadoo[k].y;
setcolor(4);
circle(x22,y22,7);
circle(x22,y22,6);
setfillstyle(1,15);
floodfill(x22,y22,4);
setcolor(3);
settextstyle(0,0,0);
settextjustify(100,100);
outtextxy(x22,y22-15,chr(48+k));
setcolor(4);
line(tdophai,tdoy,toadoo[k].x,toadoo[k].y);
end;
setcolor(4);
circle(tdotrai,tdoy,7);
circle(tdotrai,tdoy,6);
setfillstyle(1,15);
floodfill(tdotrai,tdoy,4);
setcolor(3);
settextstyle(0,0,0);
settextjustify(tdotrai,tdoy);
outtextxy(tdotrai,tdoy-15,'s');
setcolor(4);
circle(tdophai,tdoy,7);
circle(tdophai,tdoy,6); 66 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. setfillstyle(1,15);
floodfill(tdophai,tdoy,4);
setcolor(3);
settextstyle(0,0,0);
settextjustify(tdophai,tdoy);
outtextxy(tdophai,tdoy-15,'t');
for i:=1 to ssv do
begin
for j:=1 to sn do
if F^[i,j]=1 then
begin
setcolor(4);
line(toado[i].x,toado[i].y,toadoo[j].x,toadoo[j].y);
end;
end;
end;
(*======================================================*)
procedure Mophong;
begin
TransMatrixFlow;
max_flow;
TransresultM;
Initgr;
display;
{ setbkcolor(8);}
Outtextxy(140,45,'GRAPH INPUT');
Outtextxy(478,45,'GRAPH OUTPUT ');
toado1;
toado2;
READLN;
closegraph;
end;
(*-----------------------------------------------------*)
procedure phannhom;
begin
{if ok then
begin}
TransMatrixFlow;
max_flow;
TransresultM;
initgr;
display;
Outtextxy(140,45,'MA TRAN A BIEU DIEN MANG G '); 67 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. Outtextxy(478,45,'LUONG CUC DAI TRONG MANG G ');
vechu1;
{ end
else begin
initgr;
display;
setcolor(4);
outtextxy(50,100,'Khong phan nhom duoc');
end;}
READLN;
closegraph;
end;
(*=========================================================*)
(* CHON LENH LAM VIEC *)
(*=========================================================*)
function menu(c:byte):word;
var
cmd:word;
begin
if c=68 then
begin
cmd:=menubar($70,$20,1); {(*$20,$70 mau nen:3bit cao, mau chu :4 bit
thap*)}
case cmd of
IDNEW : newfile;
IDOPEN : openfile;
IDSAVE : savefile;
IDPNHOM: phannhom;
IDMOPHONG :Mophong;
IDABOUT :about;
end;
repaint;
end;
menu:=cmd;
end;
(*-----------------------------------------------------------------------*)
procedure appinit;
begin
init;
textmode(C80);
repaint;
end;
(*------------------------------------------------------------------------*)
var 68 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. cmd:word;
begin
appinit;
repeat
cmd:=menu(port[$60]);
until (cmd=0)or(cmd=IDEXIT)OR(port[$60]=1) ;
finish;
end.
II. MỘT SỐ GIAO DIỆN CHÍNH CỦA CHƯƠNG TRÌNH
1. Giao diện chính 69 Generated by Foxit PDF Creator © Foxit Software
http://www.foxitsoftware.com For evaluation only. 2. Giao diện nhập ma trân A biểu diễn mạng G = (V,E) với khả năng thông qua
các cung các đỉnh.
2. Giao diện biểu diễn mạng với luồng cực đại 70Chương 2
PHÁT BIỂU BÀI TOÁN LUỒNG TRÊN MẠNG
18
f (e) ≤ c(e),
Xv
Xw
(iii) =>(i). Theo bổ đề 1, val(f) c(X,X*) với mọi luồng f và với mọi lát cắt
(X,X*). Vì vậy, từ đẳng thức val(f) = c(X,X*) suy ra luồng f là luồng cực đại trong
mạng.
4. Thuật toán Ford – Fulkerson tìm luồng cực đại trong mạng
n
j
xij = 0 hoặc 1, j=1,2,…,n (3)
trong đó aij {0,1}, i= 1,2,…,m; j= 1,2,…,n, pi - nguyên dương, i=1,2,…,m.
Dưới đây ta dẫn ra một vài ví dụ điển hình.
3.3.1 Bài toán phân nhóm sinh hoạt
n
j
xij = 0 hoặc 1, j=1,2,…,n (3)
trong đó aij {0,1}, i= 1,2,…,m; j= 1,2,…,n, pi - nguyên dương, i=1,2,…,m.
3.3.2 Bài toán lập lịch cho hội nghị
n
j
xij = 0 hoặc 1, j=1,2,…,n (3)
trong đó aij {0,1}, i= 1,2,…,m; j= 1,2,…,n, pi - nguyên dương, i=1,2,…,m.
CHƯƠNG III
PHÂN TÍCH VÀ CÀI ĐẶT
cực đại và ma trận biểu diễn nó như sau:
III. MỘT SỐ HÀM VÀ THỦ TỤC CỦA CHƯƠNG TRÌNH NGUỒN
procedure Initgr;
var
Gd, Gm: Integer;
Radius: Integer;
begin
Gd := Detect;
InitGraph(Gd, Gm, 'D:\bp\bgi ');
if GraphResult <> grOk then
Halt(1);
end;
(*==================================================*)
procedure readfile;
var
i,j:word;
kt:array[1..max] of integer;
begin
readln(ff,Ssv,Sn);
for i:=1 to Ssv do
begin
for j:=1 to Sn do read(ff,C^[i,j]);
readln(ff,e[i]);
end;
end;
(*==============================================*)
{procedure sum_ei;
var kt:array[1..max] of integer;
snc,i,j:word;
begin