ứng dụng luồng cực đại trong bài toán tối ưu rời rạc
Đức Trọng
I. Bài toán
Xétbài toán:
Trongđó a
ij
thuộc {0,1}
p
i
nguyên dương
i = 1,2,…,m;
j = 1,2,…,n
Bài toán trên là mô hình toán học của nhiều bàitoán tối ưu tổ hợp trong thực tế. Ví dụ:
II. Vídụ
1. Bài toán phânnhóm sinh hoạt:
Cóm sinh viên và n nhóm sinh hoạt chuyên đề.Với mỗi sinh viên i biết:
- a
ij
=1, nếu sinh viêni có nguyện vọng tham gia vào nhóm j
- a
ij
=0, nếu ngượclại
- p
i
là số lượngnhóm chuyên đề mà sinh viên i phải tham dự
i=1,2,…,m; j=1,2,…,n
Trong số các cách phân các sinh viên vào nhóm chuyênđề mà họ có nguyện vọng tham gia
và đảm bảo mỗi sinh viên i phảitham gia đúng p
i
nhóm, hãy tìm cách phân phối với số
người trong nhómcó nhiều sinh viên tham gia nhất là nhỏ nhất có thể được.
Đưa vào các biến số:
x
ij
=1, nếu sinh viên i tham gia vào nhóm j
x
ij
= 0, nếu ngược lại
i=1,2,...,m ; j=1, 2,...,n, khi đó dễ thấy mô hình toán học cho bài toánđặt ra chính là bài
toán (1)-(2).
2. Bài toán lậplịch cho hội nghị:
Mộthội nghị có m tiểu ban, mỗi tiểu ban cần sinh hoạt trong một ngày tạiphòng họp phù
hợp với nó. Có n phòng họp dành cho việc sinh hoạt củacác tiểu ban. Biết:
- a
ij
=1, nếu phòng họpi là thích hợp với tiểu ban j
- a
ij
=0, nếu ngượclại
i=1,2,...,m, j=1, 2,...,n. Hãy bố trí các phòng họp cho các tiểu bansao cho hội nghị kết thúc
sau ít ngày làm việc nhất.
Đưa vào các biến số :
x
ij
= 1, nếu bố trí tiểu ban i làm việc ở phòng j
x
ij
= 0, nếu ngược lại
i=1, 2,...,m ; j=1, 2,...,n, khi đó dễ thấy mô hình toán học cho bài toánđặt ra chính là bài
toán (1)-(2), trong đó pi =1, i=1, 2,...,m.
III. Cơ sở thuật toán
Bổ đề 1:
Bài toán (1)-(2) có nghiệm tối ưu khi và chỉ khi:
Chứng minh:
Điều kiện cần là hiển nhiên vì sự tồn tại phương án của bàitoán suy ra bất đẳng thức trong
(3) được thực hiện ít nhất dưới dạng dấu đẳngthức.
Điều kiện đủ: Chỉ cần chỉ ra rằng nếu có (3) thì luôn có phươngán.
Giả sử (3) đúng, gọi:
Do(3) là điều kiện để (1)-(2) có nghiệm nên trong phần tiếp theo ta luôngiả thiết rằng điều
kiệnđược thực hiên.
Bâygiờ ta chỉ ra rằng bài toán (1)-(2) có thể chuyển về giải một số hữuhạn bài toán luồng
cực đại trong mạng. Trước hết với mỗi k nguyêndương ta xây dựng mạng G
(k)
= (V,E) với
e thuộc E:khả năng thông qua c(e)
c(s,u
i
) = p
i
c(u
i
,v
j
) = a
ij
c(v
j
,t) = k
Bổđề 2: Giả sử vớik nào đó luồng cực đại trong mạng G
(k)
có giá trị Δ thì x* với x*
ij
= Φ
(u
i
,v
j
)là phương án của bài toán (1)-(2) trong đó Φ (u
i
,v
j
)là luồng qua (u
i
,v
j
)
Chứngminh: Thật vậy, do luồng cực đại trong mạng có giá trị Δ và là nguyên nên Φ (s,u
i
) =
p
i
và Φ (u
i
,v
j
) thuộc {0,1}với i=1,2,…,m;j=1,2,…,n
Vậy x* là phương án của bài toán (1)-(2) (đpcm).
Bổđề 3:
Giả sử x*là phương án tối ưu và k* là giá trị tối ưu của bài toán(1)-(2) thì luồng cực đại
trong G
(k*)
có giá trị Δ
Chứng minh: Do giá trị của luồng cực đại trong mạng G
(k*)
không vượt qu Δ, nên để chứng
minh bổ đề ta chỉ cần chỉ ra luồngvới giá trị Δ trong mạng G
(k*)
.
Ta xây dựng luồng Φ như sau:
Dễ dàng chứng minh Φ là luồng trong mạng G
(m)
có giá trị Δ.(đpcm)
Bổđề 4:
Nếu k=m thìluồng cực đại trong mạng G
(m)
có giá trị Δ.
Chứng minh:
Lập luận tương tự bổ đề 3 ta chỉ cần chỉ ra luồng với giátrị Δ trong mạng G
(m)
.
Thậtvậy, giả sử x* là nghiệm bài toán (1)-(2) được xây dựngtheo công thức như bổ đề 1,
xây dựng Φ theo bổ đề 3 ta có luồng giá trị Δ.(đpcm)
IV. Thuậttoán:
Từ nhận xét 2 và 3 suy ra việc giải bài toán (1)-(2) là tìm k*nguyên dương nhỏ nhất sao
cho luồng cực đại trong mạng G
(k*)
có giá trị Δ.Nhận xét 4 giới hạn giá trị k* thuộc [1,m].
Từ đây rút ra thuật toán: áp dụng phương pháp chia nhị phântrên đoạn [1,m] tìm k* trong
mỗi bước giải bài toán tìm luồngcực đại trong.
V. Chương trình
Input: file văn bảnINPUT.TXT
- Dòng 1: Chứa 2 sốm,n (m,n ≤ 100)
- Dòng 2: Chứa n sốnguyên p
1
,p
2
,..,p
n
- Trong m dòng tiếptheo mô tả mảng a
Output: file văn bản OUTPUT.TXT
- Dòng 1 chứa giátrị tối ưu tìm được
- Các dòng sau mô tả mảng x
Chươngtrình:
UsesCrt;
Const
InputFile=’Input.Txt’;
OutputFile=’Output.Txt’;
Var
a,x:Array[1..100,1..100]of Integer;
TraceX,TraceY:Array[1..100]of Integer;
p:Array[1..100]of Integer;
Start,Finish,n,m,s,t,Delta,No:Integer;
fi,fo:Text;
ProcedureInput;
Vari,j:Integer;
Begin
Assign(fi,InputFile);
Reset(fi);
Readln(fi,m,n);
Delta:=0;
For i:=1 to m do begin
read(fi,p[i]);
Delta:=Delta+p[i];
End;
For i:=1 to m do
For j:=1 to n do read(fi,a[i,j]);
Close(fi);
s:=m+1;t:=n+1;
For i:=1 to m do a[s,i]:=p[i];
End;
FunctionFindPath:Boolean;
Var
Queue:Array[1..100]of Integer;
i,j,First,Last,v:Integer;
Begin
Fillchar(TraceX,Sizeof(TraceX),0);
Fillchar(TraceY,Sizeof(TraceY),0);
First:=1;Last:=0;
For i:=1 to m do
If x[s,i]
inc(last);
Queue[last]:=i;
traceX[i]:=-1;
end;
While First<=Last do Begin
i:=Queue[First];Inc(first);
For j:=1 to n do
If (traceY[j]=0)and(x[i,j]
traceY[j]:=i;
If x[j,t]
Finish:=j;
FindPath:=True;
Exit;
end;
For v:=1 to m do
if (TraceX[v]=0)and(x[v,j]>0) then begin
Inc(Last);
Queue[Last]:=v;
TraceX[v]:=j;
end;
end;
End;
FindPath:=False;
End;
FunctionMin(x,y:Integer):Integer;
Begin
If x
End;
ProcedureIncFlow;
VarIncValue,i,j:Integer;
Begin
IncValue:=a[finish,t]-x[Finish,t];
j:=Finish;
While j>0 do begin
i:=TraceY[j];
IncValue:=Min(IncValue,a[i,j]-x[i,j]);