Ta sẽ khảo sát sự tồn tại luồng khả thi của bài toán lưu thông. Gọi S là một tập hợp nút bất kỳ trên mạng. Ta có: ∑ ∑ ∈ ∈ = − } ) , ( : { {:( ,) } 0 A j i j j ji A ji ij x x (3.13)
KHOA CNTT –
ĐH KHTN
CHƯƠNG 3: LUỒNG CỰC ĐẠI
Do lij ≤xij ≤uij nên từ (3.13) suy ra:
∑ ∑ ∈ ∈ ≤ } ) , ( : {j i j A {j:(j,i) A} ji ij u l (3.14) Biểu thức (3.14) chính là điều kiện cần để tồn tại luồng khả thi. Nó có nghĩa là lượng luồng tối đa có thể gửi ra từ tập S phải lớn hơn lượng luồng tối thiểu có thể nhận bởi tập S.
Ta sẽ chứng minh (3.14) là điều kiện đủ. Bắt đầu từ một luồng x thỏa các ràng buộc của bài toán ngoại trừ một số vi phạm về chặn dưới. Ta sẽ từng bước biến đổi x thành luồng khả thi hoặc phát hiện ra rằng một nút nào đó trong S vi phạm (3.14).
Ứng với luồng x, ta gọi một cung (i,j) là không tương thích nếu xij <lij và tương thích nếu ngược lại.
Chọn một cung (p,q) không tương thích và biến nó thành tương thích bằng cách tăng luồng trên nó. Do điều kiện cân bằng vật chất tại các nút, để tăng luồng trên cung (p,q), ta phải tăng luồng dọc theo một hay nhiều chu trình chứa (p,q). Ta
định nghĩa mạng thặng dư như trước đây, ngoại trừ khả năng thông qua thặng dư rij được đặt bằng uij - xij. Mọi chu trình tăng trưởng chứa cung(p,q) như một cung tới phải chứa một đường đi có hướng trong G(x) cộng với cung (p,q). Ta có thể dùng thuật toán gán nhãn để tìm một đường đi từ p đến q.
Ta áp dụng thủ tục này trên mỗi cung không tương thích một lần. Sau mỗi bước, tính không tương thích của các cung sẽ giảm dần. Lặp lại quá trình này, hoặc ta sẽ nhận được một luồng khả thi, hoặc thuật toán gán nhãn không tìm ra đường đi từ p đến q đối với một cung không tương thích (p,q) nào đó.Trong trường hợp này, bài toán của chúng ta sẽ không tìm ra được lời giải. Thật vậy, gọi S là tập nút đã
được gán nhãn trong lần áp dụng cuối cùng của thuật toán gán nhãn. Rõ ràng, q∈S và p∈S = N-S. Do thuật toán gán nhãn không thể gán nhãn cho các nút thuộc S nên mọi cung (i,j)hướng từ S đến S có khả năng thông qua bằng 0. Do đó xij = uij
(i,j)∈(S,
∀ S) và xij u≤ ij (i,j)∀ ∈(S,S). Ta cũng có (p,q)∈(S,S) và xpq ≤ upq.
Thay các giá trị này vào (3.13) ta có: ∑ ∑
∈ ∈ > } ) , ( : {j i j A {j:(j,i) A} ji ij u l
KHOA CNTT –
ĐH KHTN
Kết quả này mâu thuẫn với điều kiện (3.14) Như vậy (3.14) là điều kiện đủ
cho sự tồn tại của luồng khả thi. Từđây, ta có định lý:
Định lý 3.7: điều kiện tồn tại luồng khả thi trên mạng lưu thông
Trên mạng lưu thông có chặn dưới dương tồn tại luồng khả thi khi và chỉ
khi tập đỉnh S thỏa mãn điều kiện: ∑ ∑ ∈ ∈ ≤ } ) , ( : {j i j A {j:(j,i) A} ji ij u l Định lý 3.8
Bài toán luồng khả thi có lời giải khi và chỉ khi với mọi tập con các nút S, b(S) – u[ S,S] 0 trong ≤ đó b(S) = ∑
∈S i
i b().
3.6. Cải tiến thuật toán đường tăng trưởng
Trong phần này, chúng ta sẽ xem xét một số phương pháp nhằm cải thiện tốc độ thực thi của thuật toán đường tăng trưởng. Những thuật toán đã cải tiến này có độ phức tạp đa thức.
Chúng ta có thể giảm số lần tăng luồng (augmentation) hoặc khử chúng bằng cách nào? Trong phần này chúng ta sẽ xét 3 phương pháp cơ bản sau:
1) Tăng một lượng luồng “lớn”.
2) Sử dụng các chiến lược kết hợp để giới hạn các loại đường đi tăng trưởng (augmenting path) mà chúng ta có thể sử dụng ở mỗi bước.
3) Nới lỏng các ràng buộc cân bằng khối lượng ở các bước trung gian của thuật toán, và vì thế sẽ không đòi hỏi rằng mỗi lần thay đổi luồng phải là một lần tăng luồng bắt đầu ở đỉnh nguồn và kết thúc
ởđỉnh đích.
Bây giờ chúng ta hãy lần lượt xem xét các phương pháp này. Chúng ta đã thấy ở phần trên, thuật toán đường đi tăng trưởng tổng quát có thể chậm vì chúng thực hiện một số lớn các lần tăng luồng, mỗi lần với một lượng luồng nhỏ. Quan sát này cho ta một chiến lược tự nhiên để cải tiến thuật toán đường đi tăng trưởng: tăng luồng dọc theo một đường đi có độ thông qua thặng dư lớn thì số lần tăng
KHOA CNTT –
ĐH KHTN
CHƯƠNG 3: LUỒNG CỰC ĐẠI
luồng sẽ giảm bớt. Chúng ta sẽ xây dựng một thuật toán dựa trên chiến lược này,
đó là thuật toán tỉ lệ với độ thông qua, sẽđược khảo sát ở phần sau.
Một chiến lược khác có thể thực thi và cải tiến thuật toán đường đi tăng trưởng là phát triển các phương pháp độc lập với dữ liệu độ thông qua của cung. Một trong những hướng tiếp cận này là bằng cách nào đó giới hạn các lựa chọn
đường đi tăng trưởng. Chúng ta có thể tăng luồng theo một “đường đi ngắn nhất” từ nguồn đến đích, với định nghĩa đường đi ngắn nhất là một đường đi có hướng trong đồ thị thặng dư có ít cung nhất.
Chiến lược thứ 3 là tìm “đường đi ngắn nhất” như trong thuật toán đường đi tăng trưởng ngắn nhất, nhưng không gửi luồng theo các đường đi từ nguồn tới
đích. Thay cho điều đó, chúng gửi các luồng trên các cung riêng lẻ. Chúng ta sẽ
minh họa chiến lược này bằng thuật toán đẩy luồng được trình bày ở phần sau. Khái niệm về các nhãn khoảng cách là một phần quan trọng để thực thi các thuật toán đường đi tăng trưởng ngắn nhất và đẩy luồng. Vì vậy trước khi mô tả
các thuật toán cải tiến, chúng ta bắt đầu với định nghĩa về nhãn khoảng cách.
3.6.1. Các nhãn khoảng cách
Một hàm khoảng cách d: N → Z+ {0} ∪ đối với độ thông qua thặng dư rij là một hàm từ tập các đỉnh vào tập các số nguyên không âm. Chúng ta nói một hàm khoảng cách là hợp lệ (valid) đối với một luồng x nếu nó thỏa mãn hai điều kiện sau:
d(t) = 0; (3.15)
d(i) d(j) + 1 v≤ ới mọi cung (i, j) trong đồ thị thặng dư G(x). (3.16)
Chúng ta nói d(i) là nhãn khoảng cách của đỉnh i và điều kiện (3.15) và (3.16) là các điều kiện hợp lệ. Các tính chất sau cho thấy tại sao các nhãn khoảng cách có thểđược sử dụng trong việc thiết kế các thuật toán luồng trên đồ thị.
KHOA CNTT –
ĐH KHTN
Tính chất 3.9
Nếu các nhãn khoảng cách là hợp lệ thì nhãn khoảng cách d(i) là chặn dưới của độ dài đường đi (có hướng) ngắn nhất từ đỉnh i đến đỉnh t trong đồ thị thặng dư.
Tính chất 3.10
Nếu d(s) ≥ n thì đồ thị thặng dư không chứa đường đi có hướng từ đỉnh nguồn đến đỉnh đích.
Chúng ta nói rằng các nhãn khoảng cách là chính xác nếu với mỗi đỉnh i, d(i) bằng độ dài đường đi ngắn nhất từ đỉnh i đến đỉnh t trong đồ thị thặng dư. Chúng ta có thể xác định các nhãn khoảng cách chính xác cho tất cả các đỉnh trong thời gian O(m) bằng thuật toán tìm kiếm theo chiều rộng lùi trên đồ thị bắt đầu từ đỉnh đích.
3.6.2. Thuật toán tỉ lệ với độ thông qua
Thuật toán này dựa vào ý tưởng tăng một lượng luồng lớn nhằm giảm số lần tăng luồng. Tuy nhiên ở đây, chúng ta chỉ tăng luồng theo một đường đi có độ
thông qua thặng dưđủ lớn thay vì một đường đi có độ thông qua tăng trưởng lớn nhất bởi vì chúng ta có thể dễ dàng có được đường đi này khá dễ dàng – trong thời gian O(m). Đểđịnh nghĩa thuật toán tỉ lệ với độ thông qua, ta giới thiệu một tham số∆, và với một luồng cho trước x, đồ thị thặng dư∆ được định nghĩa là một đồ
thị chứa các cung có độ thông qua thặng dư ít nhất là ∆. Gọi G(x, ∆) là đồ thị thặng dư∆. Chú ý rằng G(x,1) = G(x) và G(x, ∆) là đồ thị con của G(x). Hình 3.7 minh họa cho định nghĩa này. Hình 3.7(a) cho thấy đồ thị thặng dư G(x) và hình 3.7(b) cho thấy đồ thị thặng dư∆ G(x, ∆) với ∆ = 8.
KHOA CNTT –
ĐH KHTN
CHƯƠNG 3: LUỒNG CỰC ĐẠI
i rij j 1 2 4 3 5 10 12 4 8 13 15 6 1 2 4 3 5 10 8 13 15 7 12 (a) (b)
(a)Đồ thị thặng dư G(x); (b) Đồ thị thặng dư G(x, ) với = 8∆ ∆
Hình 3-5 Minh họa đồ thị thặng dư
Thuật toán Đo độ thông qua
begin x := 0; ∆ := 2[log U] ; while ∆ ≥ 1 do begin while G(x, ∆) chứa một đường đi từđỉnh s đến đỉnh t do begin xác định một đường đi P trong G(x, ∆); δ:= min{rij : (i, j) ∈ P}; tăng δ đơn vị luồng trên P và cập nhật G(x, ∆); end; ∆ := ∆/2; end; end;
Thuật toán đo độ thông qua giải bài toán luồng cực đại trong O(m log U) lần tăng luồng và chạy trong thời gian O(m2 log U).
KHOA CNTT –
ĐH KHTN
3.6.3. Thuật toán đường đi tăng trưởng ngắn nhất
Thuật toán đường đi tăng trưởng ngắn nhất luôn tăng luồng theo đường đi ngắn nhất từ nguồn đến đích trong đồ thị thặng dư. Một phương pháp tự nhiên cho bài toán này là tìm đường đi ngắn nhất trên đồ thị thặng dư bằng thuật toán tìm kiếm theo chiều rộng. Tuy nhiên, phương pháp này tốn quá nhiều thời gian. Ta có thể cải tiến nó bằng cách khai thác tính chất khoảng cách nhỏ nhất từđỉnh i bất kỳ đến đỉnh đích t là không giảm trong tất cả các lần tăng luồng. Thuật toán đường đi tăng trưởng ngắn nhất thực thi bằng cách tăng luồng theo các đường đi có thể chấp nhận. Nó tạo ra một đường đi có thể chấp nhận bằng cách thêm từng cung tại mỗi thời điểm. Thuật toán chứa một đường đi có thể chấp nhận bộ phận (nghĩa là
đường đi từ đỉnh s đến đỉnh i chỉ chứa các cung có thể chấp nhận) và thực hiện hoạt động tiến tới hoặc quay lui từ đỉnh cuối cùng trên đường đi này, ta gọi điểm này là điểm hiện hành. Nếu điểm hiện hành i có (gắn với) cung có thể chấp nhận (i, j), chúng ta thực thi một hành động tiến tới và thêm cung (i, j) vào đường đi có thể chấp nhận bộ phận; ngược lại, chúng ta sẽ thực thi một hành động quay lui và quay lại cung trước đó. Ta lặp lại các hành động này đến khi đường đi có thể chấp nhận bộ phận gặp đỉnh đích và khi đó chúng ta sẽ thực hiện quá trình tăng luồng. Chúng ta lặp lại quá trình này đến khi luồng đạt giá trị cực đại.
Thuật toán đường đi tăng trưởng ngắn nhất;
begin x := 0; xác định các nhãn khoảng cách chính xác d(i); i := s; while d(s) < n do begin if i có một cung có thể chấp nhận then begin advance(i); if i = t then augment và đặt i = s end
KHOA CNTT –
ĐH KHTN
CHƯƠNG 3: LUỒNG CỰC ĐẠI
else retreat(i)
end; end;
Hàm Tiến tới (i) begin
cho (i, j) là cung có thể chấp nhận trong A(i); pred(j) := i và i := j;
end;
HàmQuay lui (i)
begin
d(i) := min{d(j) + 1: (i, j) ∈ A(i) và rij > 0}; if i s then i := pred(i); ≠
end;
Hàm Tăng luồng begin
dùng chỉ số chỉ đỉnh trước pred(i) để xác định đường đi tăng trưởng P từ
nguồn đến đích.
δ:= min{rij : (i, j) ∈ P};
tăngδ đơn vị luồng theo đường đi P;
end;
Thuật toán đường đi tăng trưởng ngắn nhất chạy trong thời gian O(n2m).
Sự cải tiến trong thực tế
Thuật toán đường đi tăng trưởng ngắn nhất kết thúc khi d(s) n. Thực tế
cho thấy thuật toán này tốn quá nhiều thời gian để gán lại nhãn cho các đỉnh và phần lớn thời gian cho việc này được thực hiện sau khi đã xác định được giá trị
KHOA CNTT –
ĐH KHTN
trị luồng cực đại. Chúng ta sẽđưa ra một kỹ thuật có khả năng phát hiện lát cắt nhỏ
nhất và vì thế xác định được sự hiện diện của luồng cực đại trước khi nhãn của
đỉnh s thỏa điều kiện d(s) ≥ n.
Để thực thi phương pháp này, chúng ta dùng một mảng numb có n phần tử, với chỉ số từ 0 đến n – 1. Giá trị numb(k) là số lượng đỉnh có nhãn khoảng cách bằng k. Thuật toán khởi tạo mảng này bằng cách tính các nhãn khoảng cách bằng thuật toán tìm kiếm theo chiều rộng. Các giá trị dương trong mảng numb liên tiếp nhau (nghĩa là numb(0), numb(1), numb(2), …, numb(l) là các số dương đến chỉ số
l và tất cả các mục còn lại sẽ là 0). Do đó khi thuật toán tăng nhãn khoảng cách của một đỉnh từ k1 đến k2, nó trừ 1 từ numb(k1) và cộng 1 vào numb(k2), và kiểm tra xem numb(k1) có bằng 0 hay không. Nếu numb(k1) = 0, thuật toán kết thúc.
3.6.4. Thuật toán đẩy luồng
Thuật toán này tổng quát hơn, mạnh hơn, và linh động hơn các thuật toán
đường đi tăng trưởng. Như đã thấy ở phần trên, các thuật toán đường đi tăng trưởng tăng luồng theo các đường đi, hoạt động cơ bản này có thể được tách ra thành những hoạt động cơ bản hơn là gửi luồng theo các cung riêng lẻ. Theo cách
đó, gửi một luồngδđơn vị theo một đường đi gồm k cung được tách ra thành k hoạt động cơ bản là gửiδ đơn vị luồng theo từng cung trên đường đi. Chúng ta gọi mỗi thao tác cơ bản này là một lần đẩy.
Thuật toán đẩy luồng đẩy luồng theo các cung riêng lẻ thay vì trên một
đường đi tăng trưởng do đó nó không thỏa các ràng buộc khối lượng ở các bước trung gian. Thực tế, các thuật toán này cho phép luồng đi vào một đỉnh vượt quá luồng đi ra đỉnh đó. Như vậy , ta có hàm x: A → R thỏa ràng buộc giới hạn và: x ∑ ∈ } ) , ( : {j ji A ji - ∑ x ∈ } ) , ( ij 0 ≥ ∀ i ∈ N – {s,t}. : {j i j A
Với luồng cho trước x, ta định nghĩa sự vượt quá của mỗi đỉnh i ∈ N như
sau: e(i) = ∑ x ∈ } ) , ( : {j ji A ji - ∑ x ∈ } ) , ( : {j i j A ij
e(i) 0 với mọi i ∈ N – {s,t}. Hơn nữa, không có cung nào xuất phát từ đỉnh t nên e(t) 0. Vì vậy đỉnh s là đỉnh duy nhất có giá trị vượt quá của đỉnh âm.
≥ ≥
KHOA CNTT –
ĐH KHTN
CHƯƠNG 3: LUỒNG CỰC ĐẠI
Chúng ta gọi một đỉnh có giá trị vượt quá âm là một đỉnh linh động và qui
ước rằng đỉnh nguồn và đích không bao giờ là đỉnh linh động. Thao tác cơ bản của thuật toán này là chọn một đỉnh linh động và cố gắng để xóa bỏ sự vượt quá của nó bằng cách đẩy luồng đến đỉnh kề với nó. Nhưng luồng nên được gửi đến đỉnh nào? Vì chúng ta muốn gửi luồng đến đỉnh đích nên chúng ta đẩy luồng đến các đỉnh gần đích hơn. Cũng như thuật toán đường đi tăng trưởng ngắn nhất, chúng ta đo mức độ gần đích bằng các nhãn khoảng cách vì thế gửi luồng đến gần đích hơn tương đương với đẩy luồng qua các cung có thể chấp nhận. Vì vậy chúng ta chỉ gửi luồng qua các cung có thể chấp nhận. Nếu đỉnh linh động đang xét không có cung có thể chấp nhận thì chúng ta tăng nhãn khoảng cách của nó để chúng ta có thể tạo ra ít nhất một cung có thể chấp nhận. Thuật toán kết thúc khi đồ thị không chứa
đỉnh linh động nào nữa. Dưới đây là các hàm và thuật toán đẩy luồng.
Thủ tục Tiền thực thi; begin x := 0; tính các nhãn khoảng cách chính xác d(i); xsj := usj với mỗi cung (s, j) ∈ A(s); d(s) := n; end; Thủ tục Đẩy/Gán lại nhãn(i) begin
if đồ thị chứa một cung có thể chấp nhận (i, j) then
push δ := min{e(i), rij} đơn vị luồng từđỉnh i đến đỉnh j
else thay d(i) bằng min{d(j) + 1 : (i, j)∈ A(i) và rij > 0};
KHOA CNTT – ĐH KHTN Thuật toán Đẩy luồng begin Tiền thực thi; while đồ thị chứa một đỉnh linh động do begin chọn một đỉnh linh động i; Đẩy/gán lại nhãn(i); end; end;
Đẩy δ đơn vị luồng từđỉnh i đến đỉnh j sẽ giảm e(i) và rijđiδ đơn vị và tăng e(j) và rji lênδ đơn vị. Chúng ta nói rằng một lần đẩyδ đơn vị luồng trên một cung (i, j) là bão hòa nếuδ = rij và ngược lại là chưa bão hòa. Một lần đẩy chưa bão hòa tại đỉnh i giảm e(i) thành 0. Chúng ta gọi quá trình tăng nhãn khoảng cách của một