Thuật toán bắt cặp lớn nhất trên đồ thị phân đôi

Một phần của tài liệu NGHIÊN cứu một số vấn đề của LÝTHUYẾT đồ THỊ ỨNG DỤNG TRONG GIẢIQUYẾT một số bài TOÁN THỰC tế (Trang 64)

Thuật toán này dùng ý tưởng của thuật toán đường tăng trưởng để giải bài toán bắt cặp. Bắt đầu một sự bắt cặp thích hợp M ( M có thể bằng null ). Sau đó, với mỗi nút chưa bắt cặp p∈ N, ta lặp lại các bước sau: xác định một đường tăng trưởng P bắt đầu tại nút p. Nếu tìm được P thì thay M bằng M⊕P, ngược lại xoá nút p và các cạnh kề với nó trong đồ thị.

Phương pháp đơn giản để giải bài toán bắt cặp là xây dựng một cây tìm kiếm có gốc là nút p sao cho mọi đường đi trên cây bắt đầu từ nút gốc đến tất cả

KHOA CNTT –

ĐH KHTN

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP

các nút còn lại đều là đường đi xen kẽ. Để cho tiện lợi, ta gọi p là nút gốc của cây và cây này được gọi là cây xen kẽ. Ta gọi các nút trong cây này là các nút đã được gán nhãn, các nút còn lại là các nút chưa được gán nhãn. Các nút đã gán nhãn được chia làm hai loại: nút chẵn và nút lẻ. Khi một nút chưa được bắt cặp (khác nút gốc) có nhãn lẻ thì đường đi từ nút gốc đến nút này là một đường tăng trưởng. Ta có thể

gán nhãn “E” cho các nút nhãn chẵn và “O” cho các nút nhãn lẻ.

Hình 5.4 sau cho thấy sự tăng trưởng của cây tìm kiếm trên đồ thị (hình 5.4a). Giả sử ta sẽ kiểm tra các nút trong LIST theo thứ tự first-in, first-out và quét các nút trong danh sách các nút kề theo thứ tự tăng dần theo chỉ số của nút. Thuật toán sẽ kiểm tra các nút theo thứ tự 1-2-4-3-7-6-8-5. Kết quả là cây xen kẽ (hình 5.4b) có đường tăng trưởng là 1-4-7-8. 1 2 5 8 7 4 3 6 1 2 5 8 7 4 3 6 Gốc Gốc E O E O O E O E (a) (b)

(a) Đồ thị ban đầu; (b) Cây xen kẽ của nó

Hình 5-4 Phát triển 1 cây xen kẽ

Sau đây là thuật toán bắt cặp trên mạng phân đôi giúp tìm ra sự bắt cặp cực

đại trong mạng.

Thuật toán bắt cặp begin

M:= φ ;

for each nút p thuộc N

if nút p chưa bắt cặp then begin

KHOA CNTT – ĐH KHTN Xoá nút p và tất cả các cạnh kề với nó trong G ; end M* = M ; end ;

Thuật toán tìm kiếm(p,found)

begin found:= false ; xoá nhãn cho tất cả các nút ; gán nhãn chẵn cho nút p ; khởi tạo LST = {p} ; while LIST ≠φ begin

xoá nút i trong LIST ;

if i là nhãn chẵn then kiểm tra chẵn(i,found) ;

else kiểm tra lẻ(i,found) ;

if found = true then thoát ;

end; end;

Thuật toán kiểm tra chẵn(i,found)

begin

for each nút j thuộc A(i)

begin if j chưa được bắt cặp then begin đặt p: = j và pred(q):= i ; found:= true ; thoát ; end if j đã bắt cặp và chưa gán nhãn then begin

KHOA CNTT –

ĐH KHTN

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP (adsbygoogle = window.adsbygoogle || []).push({});

đặt pred(j):=i ; gán cho j nhãn lẻ ; thêm j vào LIST ;

end end

end

Thuật toán kiểm tra lẻ (i,found)

begin chọn j là nút bắt cặp với i ; if j chưa gán nhãn then begin đặt pred(j):= i ; gán cho j nhãn chẵn ; thêm j vào LIST ;

end end

Thuật toán tăng luồng begin

đi dọc theo đường tăng trưởng P bằng cách bắt đầu tại nút p và đi theo chỉ

số của nút kề trước đó ;

cập nhật lại sự bắt cặp bằng thao tác M: = M⊕P ;

end

Thuật toán chạy trong thời gian là 0(nm). Thuật toán thực hiện thủ tục tìm kiếm và tăng luồng nhiều nhất là n lần. Thời gian cho thủ tục tăng luồng là 0(n) và thủ tục tìm kiếm là 0(m). Với mỗi nút i, thuật toán thực hiện một trong hai thao tác sau

1) kiểm tra nút chẵn nếu i là nút nhãn chẵn, tốn thời gian là 0(|A(i)|).

2) kiểm tra nút lẻ nếu i là nút nhãn lẻ, tốn thời gian là 0(1). Như vậy tổng thời gian kiểm tra cho tất cả các nút là 0(∑|A((i)|).

KHOA CNTT –

ĐH KHTN

5.3. Bài toán bắt cặp có trọng số trên đồ thị phân đôi

Cho một mạng phân đôi G = (N1∪N2, A) với |N1| = |N2|, trọng lượng của cạnh là cij. Mục tiêu của bài toán là tìm một cách ghép cặp sao cho tổng trọng lượng là nhỏ nhất. Với G là một mạng có hướng, bài toán này còn được gọi là bài toán phân công, đây là một trường hợp đặc biệt của bài toán luồng có chi phí nhỏ

nhất và ta có thể phát biểu bài toán dưới dạng toán học như sau:

Cực tiểu hoá giá trị ∑ (5.1a)

A j i ij ijx c ) , ( Thoả các điều kiện sau ∑ ∈ = } ) , ( : { 1 A j i j ij xiN1 (5.1b) ∑ ∈ = A i j j ji x ) , ( : { 1 ∀iN2 (5.1c) xij≥ 0 ∀(i, j)∈A (5.1d)

Do đó, các thuật toán để giải bài toán phân công chính là các thuật toán giải bài toán luồng có chi phí cực tiểu đã được chỉnh sửa lại cho phù hợp. Sau đây là một số thuật toán được áp dụng để giải loại bài toán này.

5.3.1. Thuật toán đường đi ngắn nhất liên tiếp

Thuật toán này khi áp dụng cho bài toán phân công thì sẽ tăng một đơn vị

luồng trong mỗi vòng lặp, điều này tương đương với việc phân công cho thêm một nút trong N1. Do đó nếu S(n,m,C) là thời gian để giải bài toán tìm đường đi ngắn nhất với các cạnh có giá trị dương thì thuật toán này sẽ kết thúc trong vòng n1 vòng lặp trong thời gian 0(n1 S(n,m,C)) với n1=|N1|.

5.3.2. Thuật toán Hungary

Thuật toán này dựa trên thuật toán primal-dual của bài toán luồng có chi phí cực tiểu. Thuật toán này trước tiên chuyển bài toán luồng có chi phí cực tiểu thành bài toán có một nút cung s* và một nút cầu t*. Tại mỗi vòng lặp thuật toán này sẽ

tính toán khoảng cách của đường đi ngắn nhất từ s* đến các nút khác, cập nhật tiềm năng của nút, sau đó giải bài tián luồng cực đại bằng cách gửi một luồng lớn nhất có thể từ nút s* đến t* thông qua các cạnh với chi phí giảm bằng 0. Khi áp

KHOA CNTT –

ĐH KHTN (adsbygoogle = window.adsbygoogle || []).push({});

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP

dụng vào bài toán phân công, thuật toán này sẽ kết thúc trong vòng n1 lần lặp, mỗi vòng lặp sẽ gửi ít nhất một đơn vị luồng tương đương với việc phân công cho ít nhất một nút trong N1. Thời gian để giải bài toán tìm đừơongngắn nhất trong tất cả

các vòng lặp là 0(n1 S(n,m,C)), thời gian để tìm ra luồng cực đại là 0(n,m) (giả sử

dùng thuật toán gán nhãn để tìm luồng cực đại).Phần tính toán chủ yếu của thuật toán này là tìm đường đi ngắn nhất. Do đó, thời gian chạy của thuật toán Hungary là 0(n1,S(n,m,C)).

5.3.3. Thuật toán tỉ lệ theo chi phí

Thuật toán này được chỉnh sửa từ thuật toán tỉ lệ theo chi phí cho bài toán luồng có chi phí cực tiểu. Khi áp dụng cho bài toán phân công, mỗi lần đẩy luồng là một lần làm đầy cạnh vì thông lượng của mỗi cạnh là 1. Do đó thuật toán này giải bài toán trong thời gian là 0(nmlog(nC)).

Một bản chỉnh sửa khác của thuật toán đã cải tiến thời gian chạy còn 0( nmlog(nC)) dựa trên sự phân rã việc tính toán trong một pha thành hai pha con. Pha con đầu tiên, ta vẫn áp dụng thuật toán tỉ lệ như thường, chỉ khác ở chỗ

khi ta gán nhãn cho một nút quá 2 n lần,ta đặt nút này riêng ra và không kiểm tra

đến nó nữa. Khi ta đặt riêng ra ngoài tất cả các nút hoạt động thì ta bắt đầu pha con thứ hai. Có thể thấy rằng pha con đầu tiên cần thời gian là 0( n1m) và khi pha này kết thúc, mạng còn chứa nhiều là 0( n1) nút hoạt động. Pha con thứ hai làm cho các nút hoạt động trở thành không hoạt động bằng cách xác định các đường đi xấp xỉ ngắn nhất từ các nút thừa đến các nút thiếu và tăng một đơn vị luồng dọc theo các đường này. Do thời gian tìm ra các đường này là 0(m) nên thời gian cho pha con thứ hai là 0( n1m log(nC)).

5.4. Bài toán bắt cặp trên đồ thị tổng quát

Trong phần này chúng ta sẽ xem xét thuật bài toán bắt cặp trên một đồ thị

KHOA CNTT –

ĐH KHTN

5.4.1. Các khó khăn gặp phải trong thuật toán bắt cặp trên mạng phân đôi phân đôi

Tính chất nhãn duy nhất

Một đồ thị được xem là có tính chất nhãn duy nhất đối với một sự bắt cặp M và một nút gốc p nếu thuật toán tìm kiếm gán một nhãn có giá duy nhất cho mỗi nút mà không quan tâm đến thứ tự kiểm tra đối với các nút đã gán nhãn.

Ta có thể thấy rằng nếu đồ thị có tính chất này thì luôn tìm ra một đường tăng trưởng nếu như nó có tồn tại. Giả sử, mạng chứa một đường tăng trưởng p-i1- j1-i2-j2-…-it-jt-q từ nút p đến nút q. Nếu chúng ta kiểm tra theo thứ tự

i1,j1,i2,j2,…,chúng ta sẽ gán nhãn chẵn cho các nút p, j1, j2,…, jt. và nhãn lẻ cho các nút i1, i2, …, it, q. Vì đồ thị có tính chất nhãn duy nhất nên thuật toán sẽ gán các nhãn giống nhau cho dù thuật toán kiểm tra các nút theo thứ tự nào đi nữa. Do đó, thủ tục luôn gán nhãn lẻ cho nút q và tìm được đường tăng trưởng.

Trên thực tế thì đồ thị phân đôi sẽ thoả mãn tính chất này vì trong một mạng phân đôi G = (N,A), ta có thể phân N thành hai tập con N1 và N2 sao cho mỗi cạnh (i,j) có hai đầu thuộc hai tập khác nhau. Đối với đồ thị này, nếu nút gốc thuộc N1, tất cả các nút được gán nhãn trong N1 sẽ nhận nhãn chẵn và các nút được gán nhãn trong N2 sẽ nhận nhãn lẻ (vì một đường xen kẽ sẽ bắt đầu từ một nút thuộc N1 và kết thúc tại một nút thuộc N2) Tương tự, nếu nút gốc thuộc N2, tất cả các nút được gán nhãn trong N2 sẽ nhận nhãn chẵn còn các nút được gán nhãn trong N1 sẽ nhận nhãn lẻ. Do đó, thuật toán bắt cặp sẽ tìm được lời giải tối ưu cho mạng phân đôi.

Mạng không phân đôi, có thể không thỏa mãn tính chất nhãn duy nhất, do

đó, thuật toán có thể không tìm ra được đường tăng trưởng ngay cả khi mạng có chứa một đường tăng trưởng. Do đó, chúng ta phải dùng đến kỹ thuật thu gọn và mở rộng nụ sau:

KHOA CNTT –

ĐH KHTN

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP

5.4.2. Hoa và nụ

Một hoa được định nghĩa đối với sự bắt cặp M và nút gốc p là một đồ thị

con gồm hai phần:

™ Cuống hoa: là một đường đi xen kẽ chẵn (có số cạnh chẵn) bắt đầu tại nút gốc p và kết thúc tại một nút w bất kỳ. Trong một số

trường hợp, p có thể là w, khi đó ta nói cuống hoa rỗng.

™ Nụ: là một chu trình xen kẽ lẻ bắt đầu và kết thúc tại cùng một (adsbygoogle = window.adsbygoogle || []).push({});

điểm w của cuống hoa và không có mộ nút chung nào khác với cuống hoa. Ta gọi w là bệ.

Sau đây là hai ví dụ về hoa:

Hình 5-5 Hai vì dụ về hoa

Tính chất 5.3

™ Một cuống hoa có 2 l nút và chứa l các cạnh đã bắt cặp với l là một số nguyên không âm (a).

™ Một nụ có 2k + 1 nút, chứa k các cạnh đã bắt cặp với k là một số nguyên lớn hơn 1. Các cạnh đã bắt cặp nối tất cả các nút của nụ

ngoại trừ bệ (b).

KHOA CNTT –

ĐH KHTN

Tính chầt 5.4

Mọi nút i trong nụ (ngoại trừ bệ) đều có thể đến được từ nút gốc (hoặc từ

bệ) thông qua hai đường xen kẽ riêng biệt. Một đường có số cạnh chẵn, một đường có số cạnh lẻ. Đường đi chẵn đến nút i kết thúc bởi một cạnh đã bắt cặp, đường đi lẻđến nút i kết thúc bởi một cạnh chưa được bắt cặp.

5.4.3. Sự thu nhỏ nụ

Nhận thấy rằng, nếu ta có thể gán cho tất cả các nút trong nụ nhãn chẵn (khi tìm ra được nụ) thì thuật toán tìm kiếm sẽ luôn tìm ra một đường tăng trưởng. Có nhiều cách để thực hiện mục tiêu này, một trong những cách thông dụng nhất là thu nhỏ nụ thành một nút. Nghĩa là thay một nụ B gồm các nút có thứ tự i1-i2-…-ik- i1 bằng một nút b theo cách thức sau:

3) Tạo một nút b có danh sách các nút kề được định nghĩa như sau: A(b) = A(i1) A(i∪ 2) ∪…∪ A(ik)

4) Cập nhật danh sách nút kề của mọi nút j ∈A(b): A(j) = A(j) {b}. ∪

5) Để có thể phục hồi lại thông tin của các nút trong nụ mà ta đã thu nhỏ, ta tạo ra một danh sách liên kết đôi vòng của các nút i1, i2,…, ik, sau đó xoá các nút này và tất cả các cạnh kề với chúng trong mạng.

Kết quả, ta có được một mạng mới Gc = (Nc, Ac) gọi là mạng thu gọn. Gọi Ac(i) là danh sách nút kề của nút i trong mạng Gc và Mc là một sự bắt cặp trong mạng mới này.

KHOA CNTT –

ĐH KHTN

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP

Ở hình 5.6: cành hoa 1-2-3-4-5-6-7-3 chứa nụ 3-4-5-6-7-3. Thu gọn tất cả

các nút này thành một nút mới là nút 11, ta được đồ thị mới như hình 5.6 b. Mỗi lần thu gọn sẽ tạo ra một nút mới. Để phân biệt nút này với các nút trong mạng ban

đầu, ta gọi nó là nút giả. Lưu ý là nút giả luôn là nút chẵn vì nó gộp toàn bộ nụ vào bệ mà bệ luôn là nút chẵn. Vì danh sách nút kề của nút giả là hợp của danh sách nút kề của các nút chứa trong nút giả nên việc quét danh sách nút kề của nút giả

cho phép ta đi đến tất cả các nút mà ta có thểđến được từ các nút trong nụ. Do đó việc thu nhỏ toàn bộ nụ thành một nút giả chẵn tương đương với việc gán nhãn chẵn cho tất cả các nút của nụ trong mạng ban đầu.

5.4.4. Thuật toán bắt cặp trên đồ thị không phân đôi

5.4.4.1. Thuật toán

Thủ tục tìm kiếm (p, found)

begin

for all nút i, đặt Ac(i) = A(i) ; found:= false ; xoá nhãn cho tất cả các nút ; gán nhãn chẵn cho nút i ; khởi tạo LIST:={p} ; while LIST ≠φ begin (adsbygoogle = window.adsbygoogle || []).push({});

xoá nút i trong LIST ;

if i có nhãn chẵn thì then kiểm tra chẵn (i,found) ;

else kiểm tra lẻ (i,found) ;

if found = true then thoát ;

end end

KHOA CNTT –

ĐH KHTN

Thủ tục kiểm tra chẵn(i,found) begin

for each nút j thuộc Ac(i)

begin if j là nút nhãn chẵn then begin thu gọn (i,j) ; thoát ; end if j chưa được bắt cặp then begin đặt q:= j ; pred(q):= i ; found:= true ; thoát ; end if j chưa được bắt cặp và chưa gán nhãn then begin đặt pred(j): = i; gán j nhãn lẻ ; thêm j vào LIST ;

end end end Thủ tục kiểm tra lẻ(i,found) begin chọn nút j bắt cặp với nút i ;

if j có nhãn lẻthen thu gọn (i,j) và thoát ;

if jchưa được bắt cặp và chưa được gán nhãn then begin

KHOA CNTT –

ĐH KHTN

CHƯƠNG 5: SỰ PHÂN CÔNG VÀ XẾP CẶP

đặt pred(j):= i ; gán nhãn chẵn cho j ; thêm j vào LIST ;

end end Thủ tục thu gọn (i,j) begin lần theo chỉ mục các nút cha của nút i để xác định nụ B ; tạo mới một nút b ; Lập Ac(b) = ∪kBAc(k) ; gán nhãn chẵn cho b ; thêm b vào LIST ;

for each nút j thuộc Ac(b) cập nhật Ac(j) = Ac(j) {b} ; ∪

tạo một danh sách liên kết đôi vòng của các nút thuộc B ; xoá các nút trong B khỏi mạng và cập nhật lại cấu trúc dữ liệu ;

end

Thủ tục tăng luồng begin

đi dọc đường tăng trưởng P’ bắt đầu từ nút p, lần theo chỉ mục các nút cha ;

if P’ chứa nút giảthen mở rộng nụ tương ứng và thu được một đường tăng

Một phần của tài liệu NGHIÊN cứu một số vấn đề của LÝTHUYẾT đồ THỊ ỨNG DỤNG TRONG GIẢIQUYẾT một số bài TOÁN THỰC tế (Trang 64)