Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 15 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
15
Dung lượng
1,76 MB
Nội dung
PHẦN PHỤ LỤC Phụ lục Bài toán luồng cực đại Cho mạng G=(V,E) Hãy tìm luồng f* mạng với giá trị luồng val(f*) lớn Luồng ta gọi luồng cực đại mạng Bài tốn xuất nhiều ứng dụng thực tế Chẳng hạn cần xác định cường độ lớn dòng vận tải hai nút đồ giao thơng Trong thí dụ lời giải toán luồng cực đại cho ta đoạn đường xe đông chúng tạo thành chỗ hẹp tương ứng dòng giao thơng xét theo hai nút chọn Một thí dụ khác xét đồ thị tương ứng với hệ thống đường ống dẫn dầu, ống tương ứng với cung, điểm phát coi tàu chở dầu, điểm thu bể chứa, điểm nối ống nút đồ thị, khả thông qua cung tương ứng với tiết diện ống Cần phải tìm luồng dầu lớn bơm dầu từ tàu chở dầu vào bể chứa Định lý: Các mệnh đề tương đương: (i) f luồng cực đại mạng (ii) Khơng tìm đường tăng luồng f (iii) Val(f)=c(X,X*) với lát cắt (X,X*) (Ta gọi lát cắt (X,X*) cách phân hoạch tập đỉnh V mạng thành hai tập X X*=V\X, s∈ X t ∈ X*.) Định lý sở để xây dựng thuật tốn lặp sau để tìm luồng cực đại mạng: Bắt đầu từ luồng tất cung (ta gọi luồng luồng không), lặp lại bước lặp sau thu luồng mà khơng cịn đường tăng: Bước lặp tăng luồng (Ford – Fulkerson): Tìm đường tăng P luồng có, tăng luồng dọc theo đường P Khi có luồng cực đại, lát cắt hẹp tìm theo thủ tục mô tả việc chứng minh định lý Thuật tốn Ford-Fulkerson mơ tả thủ tục sau đây: Procedure Luongcucdai; Begin Stop := false; While not Stop If < Tìm đường tăng luồng P> then < Tăng luồng dọc theo P> Else Stop := true; End; 158 Để tìm đường tăng luồng G(f) sử dụng thuật tốn tìm kiếm theo chiều rộng (hay tìm kiếm theo chiều sâu), đỉnh s 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 để giải toán luồng cực đại mạng Thuật toán luồng chấp nhận mạng (có thể luồng khơng) , sau ta tăng luồng cách tìm đường tăng luồng Để tìm đường tăng luồng ta áp dụng phương pháp gán nhãn cho đỉnh Mỗi đỉnh q trình thực thuật tốn ba trạng thái: chưa có nhãn, có nhãn chưa xét, có nhãn xét Nhãn đỉnh v gồm hai phần có hai dạng sau : [ + p (v) , ε (v) ] [ − p(v), ε (v) ] Phần thứ +p(v) (-p(v)) cần tăng giảm luồng theo cung (p(v),v)( cung (v,p(v)) phần thứ hai ε (v) lượng lớn tăng giảm luồng theo cung Đầu tiên có đỉnh s khởi tạo nhãn nhãn chưa xét, tất đỉnh lại chưa có nhãn Từ s ta gán nhãn cho tất đỉnh kề với nhãn đỉnh s trở thành xét Tiếp theo, từ đỉnh v có nhãn chưa xét ta lại gán nhãn cho tất đỉnh chưa có nhãn kề với nhãn đỉnh v trở thành xét Quá trình lặp lại đỉnh t trở thành có nhãn nhãn tất đỉnh có nhãn đầu xét đỉnh t khơng có nhãn Trong trường hợp thứ ta tìm đường tăng luồng, cịn trường hợp thứ hai luồng xét không tồn đường tăng luồng (tức luồng cực đại) Mỗi tìm đường tăng luồng, ta lại tăng luồng theo đường tìm được, sau xố tất nhãn đổi với luồng thu lại sử dụng phép gán nhãn đỉnh để tìm đường tăng luồng Thuật tốn kết thúc luồng có mạng khơng tìm đường tăng luồng Hai thủ tục tìm đường tăng luồng mơ tả sau : Procedure Find-path; { Thủ tục gán nhãn đường tăng luồng p[v], ∈ ε [v] nhãn đỉnh v; VT danh sách đỉnh có nhãn chưa xét ; c[u,v] khả thông qua cung (u,v),u,v ∈ V; f[u,v] luồng cung (u,v), (u,v ∈ V); } BEGIN p[s] := s ; ε [s] := +∞ ; VT := {s}; Pathfound := true; While VT {} BEGIN 159 u ⇐ VT ;( * lấy u từ VT *) For v∈ V 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] := { ε [u],c[u,v]-f[u,v] }; VT:=VT ∪ {v};(* nạp v vào danh sách đỉnh có nhãn *) If v = t then exit; End Else If (c[v,u] > 0) and (f[v,u] < 0) then Begin P[v] := u ; ε [v] := { ε [u] , f[u,v] }; VT:=VT ∪ {v};(* nạp v vào danh sách đỉnh có nhãn *) If v = t then exit; End; End; End; 160 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 begin v := p[u]; if v > 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ể thuật toán Ford_fulkerson } Begin (* khởi tạo luồng với giá trị *) For u ∈ V For v ∈ V f[u,v] :=0; Stop := false; While not Stop begin find_path; If pathfound then Inc_flow Else Stop:=true; End; < Luồng cực đại mạng f[u,v], u,v ∈ V > < Lát cắt hẹp (VT , V\ VT) > End; 161 Chương trình sau chương trình phục vụ cho việc học tập giảng dạy tốn tìm luồng cực đại mạng Chương trình sau xây dựng cơng cụ lập trình Delphi Các chức chương trình: Ta xây dựng chương trình bao gồm chức sau: * Tóm tắt thuật tốn Ford – Fulkeson * Hiển thị bước thực ứng với ví dụ cụ thể Tóm tắt thuật tốn Ford – Fulkerson : Chức có mục đích giúp cho người sử dụng nắm vững thuật toán trước vào thí dụ cụ thể Hiển thị bước thực tốn: Do chương trình nhằm mục đích phục vụ cho việc dạy học mơn Tốn rời rạc nên chức việc hiển thị chi tiết bước giải tốn ứng với tưng thí dụ cụ thể giúp cho người sử dụng hiểu rõ thuật toán Cấu trúc liệu cài đặt thuật toán: Cấu trúc liệu: Đồ thị lưu giữ dạng tập đỉnh tập cạnh Mỗi đỉnh lưu theo cấu trúc Record sau: L_TypeDinh = record Ten:String; ToaDo:L_TypeToaDo; MucKichHoat:Byte; end; Trong đó: - Biến Ten có kiểu String , lưu giữ tên đỉnh (mặt định V0,V1,…) - Biến ToaDo có kiểu L_TypeToaDo, lưu giữ toạ độ x, y đỉnh có cấu trúc Record sau : L_TypeToaDo = record x,y:integer; end; Biến Muckichhoat có kiểu Byte lưu giữ mức độ kích hoạt đỉnh (mỗi đỉnh có mức kích hoạt khác nhau), biến dùng để xác định đỉnh đầu, đỉnh cuối, đỉnh hẹp… 162 Tập cạnh đồ thị lưu theo cấu trúc Record, cấu trúc cạnh lưu trữ sau: L_TypeCanh = record DinhDau,DinhCuoi:Integer; TrongSo:L_TypeChiphi; end; : Biến DinhDau có kiểu Integer, lưu giữ số đỉnh đầu cạnh Biến DinhCuoi có kiểu Integer, lưu giữ số đỉnh cuối cạnh Biến TrongSo có kiểu L_TypeChiPhi, lưu giữ giá khả thơng qua cạnh xét Kiểu L_TypeChiPhi Record có dạng sau : L_TypeChiPhi = record Gia:real; kntq:real; end; Cài đặt thuật tốn: Như trình bày phần , thuật toán Ford –Fulkerson cài đặt cách kết hợp thủ tục Find-Path (thủ tục gán nhãn tìm đường tăng luồng) Inc-Flow (thủ tục tăng luồng theo đường tăng) Đây phần cài đặt chi tiết thuật toán Ford – Fulkerson (viết theo ngơn ngữ lập trình Delphi): 163 procedure L_find_path(var L_G1:L_typedothi); { thu tuc gan nhan tim duong tang luong: L_p[v],L_nhan,L_e[v] la nhan cua dinh v; L_v la danh sach cac dinh co nhan nhung chua xet; 164 } VAR x,y:integer; ok:boolean; a1,b1,k1,l1:real; t,t1,i:integer; BEGIN for i:=0 to L_G1.sodinh-1 L_p1[i]:=-1; L_p1[0]:=0; L_nhan[0]:=true; L_e[0]:=vocung; L_v:=[0] ; L_v1:=[0]; L_pathfound:=true; While L_v[] Begin ok:=true; x:=0; While (x0) and (b10) and (l1>0) then Begin L_p1[y]:=x; L_nhan[y]:=false; L_e[y]:=L_min(L_e[x],l1); L_v:=L_v+[y]; L_v1:=L_v1+[y]; If y=L_G1.sodinh-1 then Begin exit; End; End; End; End; L_pathfound:=false; end; procedure L_Inc_flow(var L_G1:L_typedothi); { tang luong theo duong tang } 167 var x,y,t,t1:integer; tang,a,k:real; s,s1,s2,s3,s4:string; ok:boolean; begin x:=L_G1.sodinh-1; y:=L_G1.sodinh-1; tang:=L_e[L_G1.sodinh-1]; ok:=false; while x0 begin y:=L_p1[x]; L_giatri(L_G1,x,y,t,a,L_b); {a:=c[x,y],b:=f[x,y]} L_giatri(L_G1,y,x,t1,k,L_l); {k:=c[y,x],l:=f[y,x]} if L_nhan[x] then L_G1.dscanh[t1].trongso.gia:=L_G1.dscanh[t1].trongso.gia+tang else begin L_G1.dscanh[t].trongso.gia:=L_G1.dscanh[t].trongso.gia-tang; ok:=true; end; 168 x:=y; end; end; procedure L_luongcucdai(L_G:L_typedothi; var L_G1:L_typedothi;var gt:real); { thu tuc the hien thuat toan Ford_fulkerson } var x,y,z,t,i,j,t1,t2:integer; a1,b1,f:real; ok1,stop:boolean; s,s1,ch,ch1,a:string; begin L_G1.SoDinh:=L_G.SoDinh ; L_G1.socanh:=L_G.socanh; setlength(L_p1,L_G1.SoDinh); setlength(L_nhan,L_G1.SoDinh ); setlength(L_e,L_G1.SoDinh ); setlength(L_G1.DSdinh,L_G1.SoDinh ); Setlength(L_G1.dscanh,L_G1.SoCanh ); for j:=0 to L_G.SoDinh -1 L_G1.DSDinh[j]:=L_G.DSDinh[j]; 169 for j:=0 to L_G.SoCanh -1 L_G1.DSCanh[j]:=L_G.DSCanh[j]; stop:=false; while not stop begin L_find_path(L_G1); if L_pathfound then begin tam:=tam+1; if tam>1 then L_inc_flow(L_G1) else stop:=true; end; f:=0; for y:= to L_G1.sodinh-1 begin L_giatri(L_G1,0,y,t1,a1,b1); f:=f+b1; end; for y:=0 to L_G1.Socanh -1 if L_G1.DSCanh[y].DinhCuoi =L_G1.SoDinh -1 then begin break; end; tam:=0; t2:=1; while (t2