định nghĩa 12.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, t ∈ X* . Khả năng thông qua của lát cắt (X, X*) là số
c(X,X*) = ∑c(v,w) v ∈ X w ∈ X*
Bổ ựề 12.1 Giá trị của luồng f trong mạng luôn nhỏ hơn hoặc bằng khả năng thông qua của lát cắt (X, X*) bất kỳ trong nó: val(f) ≤ c(X, X*).
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ó
∑ ( ∑ f(w,v ) - ∑ f(v,w) ) = -Val(f) v∈ X w∈ N-(v) w∈ N+(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à với 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
- ∑ f(v,w) + ∑ f(v,w) = -val(f), v ∈ X v ∈ X* w∈ X* w∈ X hay là val(f) = ∑ f(v,w) - ∑ f(v,w) v ∈ X v ∈ X* w∈ X* w ∈ X Mặt khác, từ ựiều kiện 1 rõ ràng là ∑ f(v, w) ≤ ∑ c(v, w) v ∈ X v ∈ X* w∈ X* w∈ X còn - ∑ f(v,w) ≤ 0 v ∈ X* w∈ X suy ra val(f)≤c(X, X*). Bổ ựề ựược chứng minh.
Hệ quả 12.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 ra 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 qui tắc sau :
- Nếu e = (v,w) ∈ E với f(v,w) = 0, thì (v,w) ∈ Ef với trọng số c(v,w); - 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);
- Nếu e = (v,w) ∈ E với 0 < f(v,w) < c(v,w), thì (v,w) ∈ Ef với trọng số c(v,w) - f (v,w) và (w,v) ∈ Ef với trọng số f(v,w).
Các cung của Gf ựồng thời cũng là cung của G ựược gọi là cung thuận, các cung còn lại ựược gọi là cung nghịch. đồ thị Gf ựược gọi là ựồ thị tăng luồng.
Vắ dụ 12.1: Các số viết cạnh các cung của G ở Hình 12.1 theo thứ tự là khả năng thông qua và luồng trên cung.
Hình 12.1 Mạng G và luồng f. đồ thị có trọng số Gf tương ứng.
Giả sử P = (s = v0, v1, . . . , 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 theo qui tắc sau:
f(u,v) + ε , nếu (u,v) ∈ P là cung thuận
fỖ(u,v) = f(u,v) - ε , nếu (v,u) ∈ 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 12.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).
định lý 12.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ột 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 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 có thể ựến ựược từ ựỉ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(f) = ∑ f(v,w) - ∑ f(v,w) = ∑ f(v,w) v ∈ X v ∈ X* v∈ X w∈ X* w∈ X w∈ X*
Với v ∈ X, w ∈ X*, do (v,w) ∈ Gf, nên f(v,w) = c(v,w). Vậy val(f) = ∑ f(v,w) = ∑ c(v,w) = c(X,X*)
v ∈ X v ∈ X w∈ X* w∈ X*
(iii) ⇒ (i). Theo bổ ựề 12.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. 12.3. Thuật toán tìm luồng cực ựại
định lý 12.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 ựường tăng:
Ý tưởng của 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 có, tiếp bước 3 dưới ựây.
30 Nếu δ(P) = +∞ thuật toán kết thúc.
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ể theo thủ tục mô tả trong chứng minh định lý 12.1. Sơ ựồ của thuật toán Ford-Fulkerson có thể mô tả trong thủ tục sau ựây:
Procedure Max_Flow;
(* 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 <Tăng luồng dọc theo P> else stop:=true;
End;
để tìm ựường tăng luồng trong G(f) có thể sử dụng thuật toán tìm kiếm theo chiều rộng (hay 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ị G(f). Ford-Fulkerson ựề nghị thuật toán gán nhãn chi tiết sau ựây ựể giải bài toán luồng cực ựại 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 hai 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 luồng 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 nhãn cho tất cả các ựỉnh kề với nó và nhãn của ựỉnh s sẽ trở thành ựã xét. Tiếp theo, từ một ựỉnh v có nhãn chưa xét ta lại gán nhãn cho tất cả các ựỉnh chưa có nhãn kề với nó và nhãn của ựỉnh v trở thành ựã 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
không 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 ựã 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.
Trong ựó, thuật toán gán nhãn (The labeling algorithm) có thể ựược mô tả như sau: 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 ựể tìm ựường ựi tăng luồng.
Xuất phát với VT = {s} và s là nút ựã ựánh dấu duy nhất. Một bước lặp sẽ có VT hiện hành và gồm ba bước như sau.
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).
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 v vào tập VT.
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 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.
Hai thủ tục tìm ựường tăng luồng có thể mô tả như sau : Procedure Find-path;
{ Thủ tục gán nhãn ựường tăng luồng p[v], ∈ε[v] là nhãn của ựỉnh v;
VT là danh sách các ựỉnh có nhãn chưa xét ;
c[u,v] là khả năng thông qua của cung (u,v),u,v ∈V; f[u,v] là luồng trên cung (u,v), (u,v ∈ V); }
BEGIN p[s] := s ; ε[s] :=+∞; VT := {s}; Pathfound := true; While VT <> {} do BEGIN u ⇐ VT ; ( * lấy u từ VT *) For v∈V do If (v chưa có nhãn) then Begin
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 các ựỉnh có nhãn *) If v = t then exit; End Else
If (c[v,u] > 0) and (f[v,u] < 0) then Begin
ε[v] := min {ε[u] , f[u,v] }; VT:=VT∪{v};(* nạp v vào danh sách các ựỉnh có nhãn *) If v = t then exit; End; End; End; PathFound :=false; End; Procedure Inc_flow ;
{ thuật toán tăng luồng theo ựường tăng } Begin
v := t ; u := t ; tang := [t]; while u <> s do
begin v := p[u];
if v > 0 then f[v,u] := f[v,u] + tang else
begin v := -v;
f[u,v] :=f[u,v] Ờtang; end;
u := v ; end;
Procedure FF;
{ thủ tục thể hiện thuật toán Ford_fulkerson }
(* 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 find_path; If pathfound then Inc_flow Else Stop:=true; 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;
Ta xét vắ dụ sau ựể làm quen với thuật toán Ford-Fullkerson
Vắ dụ 12.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 ựỉnh của mạng G với luồng f ựược cho như Hình 12.2, 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 12.3. 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à 12.
Hình 12.2 Mạng G và minh họa từng bước thuật toán Ford-Fullkerson
+ Bước lặp 1: s→b→d→t, δ1 = 1 3,0 3,1 c e t d b 5,2 1,1 6,1 6,5 6,4 5,4 s
+ Bước lặp 2: s→c→d→ b→e→t, δ2 = 2
+ Bước lặp 3: Không còn ựường tăng luồng, Val(fmax) = 5+4 = 9
Hình 12.3 Mạng G với luồng cực ựại và lát cắt hẹp nhất d b 3,2 3,3 c e t 5,4 1,1 6,3 6,6 6,3 5,5 s 3,0 3,1 c(s+,3) e(b+,2) t(e+,2) d(c+,2) b(d-,2) 5,2 1,1 6,1 6,6 6,5 5,5 s (-,∞) d b 3,0 3,1 c e t 5,2 1,1 6,1 6,6 6,5 5,5 s 3,0 3,1 c(s+,3) e(b+,1) t(d+,1) d(b+,1) b(s+,1) 5,2 1,1 6,1 6,5 6,4 5,4 s (s,∞) d b 3,2 3,3 c e t 5,4 1,1 6,3 6,6 6,3 5,5 s
Lặp đỉnh xét b c d e t đường tăng luồng Giá trị tăng luồng δ 1 s s+,1 S+,3 b b+,1 b+,1 c d d+,1 sbd t 1 2 s S+,3 c c+,2 d d-,2 b b+,2 e e+,2 scdbet 2 3 s S+,1
Bảng kết quả của thuật toán Ford-Fullkerson
Giả sử là khả năng thông qua của tất cả các khung 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 sau 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ừ ựó ra có các kết quả sau:
định lý 12.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ý 12.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ồng tìm ựược 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ị của 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 thực hiện rất nhiều bước tăng luồng. Vắ dụ trong Hình 12.4 sẽ minh hoạ cho ựiều này. Hình 12.4(a) mô tả mạng cần xét với các khả năng thông qua trên các cung. Hình 12.4(b) mô tả luồng trên các cung (số 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 12.4(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, a, b, t) và (s, b, a, t) một cách luân phiên ta thu ựược luồng cực ựại.
Hình 12.4Vắ dụ tồi tệ ựối 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 nếu 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(m+n), 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(n2m2), (Cherkasky, 1977), O(nm log n) (Sleator, - Tarrjan, 1980).
Ta kết thúc mục này bởi vắ dụ minh hoạ cho thuật toán Ford_Fulkerson sau ựây. Hình 12.5(a) cho mạng G cùng với thông qua của tất cả các cung và luồng giá trị 10 trong nó. Hai số viết bên cạnh mỗi cung là khả năng thông qua của cung (số trong ngoặc) và luồng trên cung. đường tăng luồng có dạng (s, v3, v2, v6, v7, t). Ta tắnh ựược ε(t) = 1, giá trị luồng tăng từ 10 lên 1. Hình 12.5 (b) cho luồng thu ựược sau khi tăng luồng theo ựường tăng tìm ựược.
Hình 12.5 Tăng luồng dọc theo ựường tăng.
Luồng trong Hình 12.5(b) ựã là cực ựại. Lát cắt hẹp nhất
X = { s, v2, v3, v5}, X* = { v4, v6, v7, t} . Giá trị luồng cực ựại là 11.
Bài 13 Lý thuyết ựồ thị và ứng dụng
13.1. Các bài toán liên quan tới ựồ thị
13.1.1 Các bài toán liên quan tới bậc của ựồ thị
Bài toán 1 Có 20 ựội bóng thi ựấu với nhau, mỗi ựội phải ựấu một trận với từng ựội khác. Chứng minh rằng vào bất cứ lúc nào cũng có 2 ựội ựã ựấu một số trận như nhau?
Giải:
Bài toán ựược chuyển qua ựồ thị như sau:
Cho tương ứng mỗi ựội bóng với một ựỉnh của ựồ thị. Khi hai ựội ựã ựấu với nhau thì ta nối 2 ựỉnh với một cạnh. Bởi vậy bài toán ựược phát biểu dưới dạng ựồ thị :
Cho một ựồ thị gồm 20 ựỉnh. CMR bao giờ cũng có hai ựỉnh cùng bậc.
Thật vậy, trong 20 ựỉnh, không thể có ựồng thời một ựỉnh bậc 0 (chẳng hạn ựỉnh A) và một ựỉnh bậc 19(chẳng hạn ựỉnh B). Nếu ựỉnh B có bậc là 19 thì B là ựầu mút của 19 cạnh nối B với 19 ựỉnh còn lại, trong ựó có A, do ựó A là ựỉnh có bậc khác 0.Ngược lại nếu A