Bài giảng Lý thuyết đồ thị - Bài toán ghép cặp
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lý thuyết đồ thị - Bài toán ghép cặp", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- bai_giang_ly_thuyet_do_thi_bai_toan_ghep_cap.pdf
Nội dung text: Bài giảng Lý thuyết đồ thị - Bài toán ghép cặp
- Bài toán ghép cặp Graph Matching Graph Matching 1
- Bài toán ghép cặp trên đồ thị Giả sử G=(V,E) là đồ thị vô hướng, trong đó mỗi cạnh (v,w) được gán với một số thực c(v,w) gọi là trọng số của nó. Định nghĩa. Cặp ghép M trên đồ thị G là tập các cạnh của đồ thị trong đó không có hai cạnh nào có đỉnh chung. Số cạnh trong M - kích thước, Tổng trọng số của các cạnh trong M - trọng lượng của cặp ghép. Cặp ghép với kích thước lớn nhất được gọi là cặp ghép cực đại. Cặp ghép với trọng lượng lớn nhất được gọi là cặp ghép lớn nhất. Cặp ghép được gọi là đầy đủ (hoàn hảo) nếu mỗi đỉnh của đồ thị là đầu mút của ít nhất một cạnh trong cặp ghép. Graph Matching 2
- Hai bài toán Bài toán cặp ghép cực đại: Tìm cặp ghép với kích thước lớn nhất trong đồ thị G. Bài toán cặp ghép lớn nhất: Tìm cặp ghép với trọng lượng lớn nhất trong đồ thị G. Ta hạn chế xét các bài toán đặt ra trên đồ thị hai phía G = (X Y, E). Graph Matching 3
- Ví dụ Cặp ghép cực đại Cặp ghép không là cặp ghép Cặp ghép Cặp ghép hoàn hảo Graph Matching 4
- Ví dụ 12 x1 y1 3 4 x2 y2 8 3 x3 2 y3 4 6 y x4 4 Cặp ghép lớn nhất: M = {(x1, y1), (x2, y3), (x3, y2), (x4, y4)} Có trọng lượng 29. Graph Matching 5
- Bài toán cặp ghép cực đại trên đồ thị hai phía 1 6 Xét đồ thị hai phía G = (X Y, E). 2 7 Cặp ghép là tập cạnh mà không có hai cạnh nào có chung đỉnh 3 8 Bài toán: Tìm cặp ghép 4 9 kích thước lớn nhất 5 10 Graph Matching 6
- Qui về Bài toán luồng cực đại 1 6 2 7 s 3 8 t 4 9 5 10 Mỗi cạnh được thay thế bởi Mỗi cung (s, i) có kntq 1. cung có kntq 1. Mỗi cung (j, t) có kntq 1.Graph Matching 7
- Tìm luồng cực đại 1 6 2 7 s 3 8 t 4 9 5 10 Luồng cực đại từ s->t có giá trị 4. Cặp ghép cực đại có kích thước 4. Graph Matching 8
- Bài toán cặp ghép cực đại trên đồ thị hai phía Giả sử M là một cặp ghép trên G. Nếu cạnh e = (x, y) M, ta nói e là cạnh của cặp ghép (hay cạnh đậm) và các đỉnh x, y là các đỉnh đậm (hay không tự do). Nếu cạnh e = (x, y) M, thì ta nói e là cạnh nhạt còn các đỉnh x, y là các đỉnh nhạt (hay tự do). Graph Matching 9
- Đường tăng cặp ghép Một đường đi trên đồ thị G mà trong đó hai cạnh liên tiếp là không cùng đậm hay nhạt sẽ được gọi là đường đi luân phiên đậm/nhạt (hay gọi ngắn gọn là đường đi luân phiên). Đường đi luân phiên bắt đầu từ một đỉnh tự do thuộc tập X và kết thúc ở một đỉnh tự do thuộc tập Y được gọi là đường tăng cặp ghép. Graph Matching 10
- Định lý Berge Định lý 1 (Berge C). Cặp ghép M là cực đại khi và chỉ khi không tìm được đường tăng cặp ghép. CM: Điều kiện cần. Bằng phản chứng. Giả sử M là cặp ghép cực đại nhưng vẫn tìm được đường tăng cặp ghép P x0, y1, x1, y2, , xk, y0 trong đó x0 và y0 là các đỉnh tự do. Gọi EP là tập các cạnh của đồ thị nằm trên đường đi P EP = { (x0,y1), (y1, x1), , (xk, y0) }. Dễ thấy số lượng cạnh nhạt trong EP là bằng số lượng cạnh đậm của nó cộng với 1. Để đơn giản trong phần dưới đây ta đồng nhất ký hiệu đường đi P với tập cạnh EP của nó. Xây dựng cặp ghép M’ theo qui tắc: M’ = (MP) \ (MP). Dễ thấy M’ cũng là cặp ghép và rõ ràng |M’| = |M| +1. Mâu thuẫn thu được đã chứng minh điều kiện cần. Graph Matching 11
- Định lý Berge Điều kiện đủ. Giả sử cặp ghép M chưa là cặp ghép cực đại. Gọi M* là cặp ghép cực đại. Xét đồ thị G’ = (V, MM*). Rõ ràng hai cạnh liên tiếp trong mỗi đường đi cũng như mỗi chu trình trong G’ không thể thuộc cùng một cặp ghép M hoặc M*. Vì vậy, mỗi đường đi cũng như mỗi chu trình trong G’ đều là đường luân phiên M/M*. Do |M*| > |M|, nên rõ ràng là luôn tìm được ít nhất một đường đi luân phiên M/M* mà trong đó số lượng cạnh thuộc M* là lớn hơn số lượng cạnh thuộc M. Đường đi đó chính là đường tăng cặp ghép trên đồ thị G. Định lý được chứng minh. Chú ý: Trong chứng minh định lý ta không sử dụng tính hai phía của G. Do đó, Định lý 1 là đúng với đồ thị vô hướng bất kỳ. Graph Matching 12
- Thuật toán tìm cặp ghép cực đại Đầu vào: Đồ thị vô hướng G = (V, E). Bước khởi tạo. Xây dựng cặp ghép M trong đồ thị G (có thể bắt đầu từ M = ). Bước lặp. Kiểm tra tiêu chuẩn tối ưu: Nếu đồ thị G không chứa đường tăng cặp ghép thì M là cặp ghép cực đại, thuật toán kết thúc. Ngược lại, gọi P là một đường tăng cặp ghép xuất phát từ đỉnh tự do x0 X, kết thúc ở đỉnh tự do y0 Y. Tăng cặp ghép theo qui tắc M:= (MP) \ (MP), rồi lặp lại bước lặp. Graph Matching 13
- Tìm đường tăng Từ đồ thị G ta xây dựng đồ thị có hướng GM = (XY, EM) với tập cung EM được bằng cách định hướng lại các cạnh của G theo quy tắc sau: i) Nếu (x,y) ME, thì (y,x) EM; ii) Nếu (x,y) E \ M, thì (x,y) EM. Đồ thị GM sẽ được gọi là đồ thị tăng cặp ghép. Dễ thấy: Đường tăng cặp ghép tương ứng với một đường đi xuất phát từ một đỉnh tự do x0 X kết thúc tại một đỉnh tự do y0 Y trên đồ thị GM. Ngược lại, một đường đi trên đồ thị GM xuất phát từ một đỉnh tự do x0 X kết thúc tại một đỉnh tự do y0 Y sẽ tương ứng với một đường tăng cặp ghép trên đồ thị G. Vì vậy, để xét xem đồ thị G có chứa đường tăng cặp ghép hay không, có thể thực hiện thuật toán tìm kiếm theo chiều rộng trên đồ thị GM bắt đầu từ các đỉnh tự do thuộc tập X. Graph Matching 14
- Thuật toán Sử dụng cách tìm đường tăng cặp ghép theo nhận xét vừa nêu, từ sơ đồ tổng quát dễ dàng xây dựng thuật toán để giải bài toán tìm cặp ghép cực đại trên đồ thị hai phía với thời gian tính O(n3), trong đó n = max (|X|, |Y|). Graph Matching 15
- Cài đặt Cấu trúc dữ liệu Var A : Array[1 100,1 100] of Byte; (* Ma trận kề của đồ thi hai phía G *) Truoc, (* Ghi nhận đường đi *) Vo, (* Vo[x]- đỉnh được ghép với x X *) Chong : Array[1 100] of Byte; (* Chong[y]-đỉnh được ghép với y Y *) N, x0, y0, Cnt : Byte; Stop : Boolean; (* Nếu (x, y) M thì Vo[x]=y; Chong[y]=x. Vo[x]=0 => x là đỉnh nhạt; Chong[y]=0 => y là đỉnh nhạt *) Graph Matching 16
- Tìm đường tăng Procedure Tim(x:Byte); Procedure Tim_Duong_Tang; var y: Byte; begin begin Fillchar(Truoc,Sizeof(Truoc),0); For y:=1 to N do y0:=0; If (A[x,y]=1)and(Truoc[y]=0)and(y0=0) then For x0:=1 to N do begin begin Truoc[y]:=x; If Vo[x0]=0 then Tim(x0); If Chong[y] 0 then exit; else end; begin Stop:=true; y0:=y; end; Exit; end; end; end; Graph Matching 17
- Thủ tục MaxMatching Procedure Tang; var temp: Byte; Procedure MaxMatching; begin begin Inc(Cnt); Stop:=false; While Truoc[y0]<>x0 do Fillchar(Vo,Sizeof(Vo),0); begin Fillchar(Chong,Sizeof(Chong),0); Chong[y0]:=Truoc[y0]; Cnt:=0; While not Stop do Temp:=Vo[Truoc[y0]]; begin Vo[Truoc[y0]]:=y0; Tim_duong_tang; y0:=Temp; If not Stop then Tang; end; end; Chong[y0]:=x0; end; Vo[x0]:=y0; end; Graph Matching 18
- Bài toán phân công Có n công việc và n thợ. Mỗi thợ đều có khả năng thực hiện tất cả các công việc. Biết wij - hiệu quả phân công thợ i làm việc j, (i, j = 1, 2, , n). Cần tìm cách phân công thợ thực hiện các công việc sao cho mỗi thợ chỉ thực hiện một việc và mỗi việc chỉ do một thợ thực hiện, đồng thời tổng hiệu quả thực hiện các công việc là lớn nhất. Graph Matching 19
- Qui về bài toán cặp ghép lớn nhất Xây dựng đồ thị hai phía đầy đủ G = (XY, E) X={x1, x2, , xn} tương ứng với các thợ, Y = {y1, y2, , yn }- tương ứng với các công việc. Mỗi cạnh (xi, yj) được gán cho trọng số w(xi, yj) = wij. Khi đó trong ngôn ngữ đồ thị, bài toán phân công có thể phát biểu như sau: Tìm trong đồ thị G cặp ghép đầy đủ có tổng trọng số là lớn nhất. Cặp ghép như vậy được gọi là cặp ghép tối ưu. Graph Matching 20
- Cơ sở thuật toán Ta gọi một phép gán nhãn chấp nhận được cho các đỉnh của đồ thị G=(XY,E) là một hàm số f xác định trên tập đỉnh XY: f: XY R, thoả mãn f(x) + f(y) w(x,y), x X, y Y. Một phép gán nhãn chấp nhận được như vậy dễ dàng có thể tìm được, chẳng hạn phép gán nhãn sau đây là chấp nhận được f(x) = max { w(x,y): y Y }, x X, f(y) = 0 , y Y. Graph Matching 21
- Đồ thị cân bằng Giả sử có f là một phép gán nhãn chấp nhận được, ký hiệu Ef = {(x,y) E: f(x) + f(y) = w(x,y)}. Ký hiệu Gf là đồ thị con của G sinh bởi tập đỉnh XY và tập cạnh Ef . Ta sẽ gọi Gf là đồ thị cân bằng. Graph Matching 22
- Tiêu chuẩn tối ưu Định lý 2. Giả sử f là phép gán nhãn chấp nhận được. Nếu Gf chứa cặp ghép đầy đủ M*, thì M* là cặp ghép tối ưu. Chứng minh. Giả sử Gf chứa cặp ghép đầy đủ M*. Khi đó từ định nghĩa Gf suy ra M* cũng là cặp ghép đầy đủ của đồ thị G. Gọi w(M*) là trọng lượng của M*: w()() M* w e e M* Do mỗi cạnh e M* đều là cạnh của Gf và mỗi đỉnh của G kề với đúng một cạnh của M*, nên w()()() M* w e f v e M* v V Giả sử M là một cặp ghép đầy đủ tuỳ ý của G, khi đó w()()() M w e f v e M v V Suy ra w(M*) w(M). Vậy M* là cặp ghép tối ưu. Graph Matching 23
- Sơ đồ thuật toán Ta sẽ bắt đầu từ một phép gán nhãn chấp nhận được f. Xây dựng đồ thị Gf. Bắt đầu từ một cặp ghép M nào đó trong Gf ta xây dựng cặp ghép đầy đủ trong Gf. Nếu tìm được cặp ghép đầy đủ M*, thì nó chính là cặp ghép tối ưu. Ngược lại, ta sẽ tìm được cặp ghép cực đại không đầy đủ M'. Từ M' ta sẽ tìm cách sửa phép gán nhãn thành f' sao cho M' vẫn là cặp ghép của Gf' và có thể tiếp tục phát triển M' trong Gf'., v.v Quá trình được tiếp tục cho đến khi thu được cặp ghép đầy đủ trong đồ thị cân bằng. Graph Matching 24
- Điều chỉnh nhãn Giả sử M là cặp ghép cực đại trong đồ thị Gf và M chưa là cặp ghép đầy đủ của G. Ta cần tìm cách điều chỉnh phép gán nhãn f thoả mãn các yêu cầu đặt ra. Thực hiện tìm kiếm theo chiều rộng từ các đỉnh tự . do trong X. Gọi S là các đỉnh được thăm trong X, còn T là các đỉnh được thăm trong Y trong quá trình thực hiện tìm kiếm. Ký hiệu SXSTYT \;\. | S | > | T | (do mỗi đỉnh trong T đạt được từ một đỉnh nào đó trong S). Graph Matching 25
- Điều chỉnh nhãn Từ tính chất của thuật toán tìm kiếm theo chiều rộng, rõ ràng, không có cạnh nào từ S đến T*. Để sửa chữa nhãn, chúng ta sẽ tiến hành giảm đồng loạt các nhãn trong S đi cùng một giá trị nào đó, và đồng thời sẽ tăng đồng loạt nhãn của các đỉnh trong T lên . Điều đó đảm bảo các cạnh từ S sang T (nghĩa là những cạnh mà một đầu mút thuộc S còn một đầu mút thuộc T) không bị loại bỏ khỏi đồ thị cân bằng S* T* Các tập S và T trong thực hiện thuật toán. Chỉ vẽ các cạnh trong Gf. Graph Matching 26
- Điều chỉnh nhãn Khi các nhãn trong S bị giảm, các cạnh trong G từ S sang T* sẽ có khả năng gia nhập vào đồ thị cân bằng Gf. Ta sẽ tăng đến khi có thêm ít nhất một cạnh mới gia nhập đồ thị cân bằng. Có hai khả năng: Nếu cạnh mới gia nhập đồ thị cân bằng giúp ta thăm được một đỉnh không tự do y T* thì từ nó ta sẽ thăm được một đỉnh được ghép với nó trong cặp ghép x S* , và cả hai đỉnh này được bổ sung vào S và T tương ứng, và như vậy việc tìm kiếm đường tăng sẽ được tiếp tục mở rộng. Nếu cạnh mới gia nhập đồ thị cân bằng cho phép thăm được một đỉnh tự do y T* thì ta tìm được đường tăng cặp ghép, và kết thúc một pha điều chỉnh nhãn. Graph Matching 27
- Điều chỉnh nhãn Ta gọi một pha điều chỉnh là tất cả các lần sửa nhãn cần thiết để tăng được kích thước của cặp ghép M. Vì sau mỗi pha điều chỉnh kích thước của cặp ghép tăng lên 1, nên ta phải thực hiện nhiều nhất n pha điều chỉnh. Trong mỗi pha điều chỉnh, do sau mỗi lần sửa nhãn có ít nhất hai đỉnh mới được bổ sung vào danh sách các đỉnh được thăm, nên ta phải thực hiện việc sửa nhãn không quá n lần. Mặt khác, trong thời gian O(n2) ta có thể xác định được cạnh nào từ S sang T* là cạnh gia nhập đồ thị cân bằng (bằng việc duyệt hết các cạnh). Từ đó suy ra đánh giá thời gian tính của thuật toán là O(n4). Graph Matching 28
- Thuật toán Bước 0: Tìm một phép gán nhãn chấp nhận được f. Bước 1: Xây dựng đồ thị cân bằng Gf. Bước 2: Tìm cặp ghép cực đại M trong Gf. Bước 3: Nếu M là cặp ghép đầy đủ thì nó là cặp ghép lớn nhất cần tìm. Thuật toán kết thúc. Bước 4: Gọi S là tập các đỉnh tự do trong X. Thực hiện tìm kiếm từ các đỉnh trong S. Gọi T là tập các đỉnh của Y được thăm trong quá trình tìm kiếm. Bổ sung các đỉnh trong X được thăm trong quá trình tìm kiếm vào S. Bước 5: Tiến hành điều chỉnh nhãn f ta sẽ bổ sung được các cạnh vào Gf cho đến khi tìm được đường tăng, bổ sung các đỉnh mới được thăm vào S và T tương ứng như đã mô tả ở trên. Tăng cặp ghép M và quay lại bước 3. Graph Matching 29
- Tăng hiệu quả Để có được thuật toán với đánh giá thời gian tính tốt hơn, vấn đề đặt ra là làm thế nào có thể tính được giá trị tại mỗi lần sửa nhãn của pha điều chỉnh một cách nhanh chóng. Ta xác định độ lệch của các cạnh theo công thức slack(x, y) = f(x) + f(y) – c(x, y). Graph Matching 30
- Tăng hiệu quả Khi đó minslack ( x , y ) x S, y T* Rõ ràng việc tính trực tiếp theo công thức đòi hỏi thời gian O(n2). Bây giờ, nếu với mỗi đỉnh trong T* ta ghi nhận lại cạnh với độ lệch nhỏ nhất slack( yj ) min slack ( x i , y j ). xi S Graph Matching 31
- Tăng hiệu quả 2 Việc tính giá trị độ lệch slack(yj) đòi hỏi thời gian O(n ) ở đầu pha điều chỉnh. Khi tiến hành pha điều chỉnh ta có thể sửa lại tất cả các độ lệch trong thời gian O(n) do chúng bị thay đổi cùng một giá trị (do nhãn của các đỉnh trong S giảm đồng loạt đi cùng một giá trị ). Khi một đỉnh x được chuyển từ S* sang S ta cần tính lại các độ lệch của các đỉnh trong T*, việc đó đòi hỏi thời gian O(n). Tuy nhiên sự kiện một đỉnh được chuyển từ S* sang S chỉ xảy ra nhiều nhất n lần. Như vậy, mỗi pha điều chỉnh có thể cài đặt với thời gian O(n2). Do có không quá n pha điều chỉnh trong thuật toán, nên cách cài đặt này cho ta thuật toán với thời gian tính O(n3). Graph Matching 32
- Ví dụ Xét bài toán với ma trận hiệu quả Graph Matching 33
- Ví dụ Bắt đầu từ phép gán nhãn Đồ thị cân bằng Gf Cặp ghép cực đại tìm được M = {(x1,y2), (x2,y1), (x4, y4) }. Tìm kiếm theo chiều rộng bắt đầu từ đỉnh tự do x3 ta có S = { x2 , x3 }, T = {y1} Graph Matching 34
- Ví dụ Tính = min {f(x)+f(y)-w(x,y): x {x2, x3}, y {y2, y3, y4} } = 1. Tiến hành sửa nhãn, ta đi đến phép gán nhãn mới Graph Matching 35
- Ví dụ Theo đường tăng cặp ghép x3, y3, x4, y4 ta tăng cặp ghép M thành cặp ghép đầy đủ M ={(x1,y2), (x3,y1), (x2,y3), (x4,y4)}, đồng thời là cặp ghép tối ưu với trọng lượng w(M) = 4 + 2 + 5 + 2 = 13. Graph Matching 36
- Cài đặt trên Pascal const maxn = 170; type data1=array [1 maxn,1 maxn] of integer; data2=array [1 2*maxn] of integer; data3=array [1 2*maxn] of longint; var c: data1; px, py, q, queue: data2; a, b, f: data3; n, n2, k, u, z: integer; Graph Matching 37
- Khởi tạo procedure init; var i, j: integer; begin n2:= n+n; fillchar(f,sizeof(f),0); for i:=1 to n do for j:=1 to n do if f[i]<c(i,j) then f[i]:=c(i,j); k:=0; fillchar(px,sizeof(px),0); fillchar(py,sizeof(py),0); for i:=1 to n do for j:=1 to n do if (py[j]=0) and (f[i]+f[j+n]=c(i,j)) then begin px[i]:=j; py[j]:=i; inc(k); break; end; end; Graph Matching 38
- Tìm đường tăng function FoundIncPath: boolean; var dq, cq, v, w: integer; begin fillchar(q,sizeof(q),0); dq:=1; cq:=1; queue[dq]:=u; q[u]:=u; while dq<=cq do begin v:=queue[dq]; inc(dq); if v<=n then begin for w:=n+1 to n2 do if (f[v]+f[w]=c(v,w-n)) and (q[w]=0) then begin inc(cq); queue[cq]:=w; q[w]:=v; end; end else if (py[v-n]=0) then begin FoundIncPath:=true;z:=v;exit; end else begin w:=py[v-n]; inc(cq); queue[cq]:=w; q[w]:=v; end; end; FoundIncPath:=false; end; Graph Matching 39
- Tìm đỉnh tự do function FreeNodeFound :boolean; var i:integer; begin for i:=1 to n do if px[i]=0 then begin u:=i; FreeNodeFound:=true; exit; end; FreeNodeFound :=false; end; Graph Matching 40
- Tăng cặp ghép và Sửa nhãn procedure Tangcapghep; procedure Suanhan; var i, j: integer; var i, j: integer; ok: boolean; begin d: longint; j:=z; ok:=true; begin while j 0 then if ok then for j:=n+1 to n2 do begin if q[j]=0 then px[i]:=j-n; if d>longint(f[i]+f[j]-c(i,j-n)) then py[j-n]:=i; end; d:=longint(f[i]+f[j]-c(i,j-n)); j:=i; for i:=1 to n do ok:= not ok; if q[i]>0 then dec(f[i],d); end; for j:=n+1 to n2 do inc(k); if q[j]>0 then inc(f[j],d); end; end; Graph Matching 41
- Main Procedure procedure Solve; begin init; while FreeNodeFound do begin while not FoundIncPath do suanhan; Tangcapghep; end; end; Graph Matching 42
- Graph Matching 43