Ural1076
带权最大匹配,采用KM算法。复杂度O(n^4)。
首先算出把第i种垃圾全部放入第j个箱子的费用。由于要求的是最小费用,我们将费用取负,然后把垃圾看成一类节点,箱子看成一类节点,匹配之,OK。最后答案取负输出。此题也可使用最小费用流,OVER。
程序:
var
b : array[1 .. 150, 1 .. 150] of longint;
a : array[1 .. 150, 1 .. 150] of longint;
lx, ly : array[1 .. 150] of longint;
vx, vy : array[1 .. 150] of boolean;
match : array[1 .. 150] of longint;
k, ans, n, i, j : longint;
function search(x : longint) : boolean;
var
t, i : longint;
begin
search := false;
if vx[x] then exit;
vx[x] := true;
search := true;
for i := 1 to n do
if not vy[i] and (lx[x] + ly[i] = b[x, i]) then begin
vy[i] := true;
t := match[i];
match[i] := x;
if (t = 0) or (search(t)) then exit;
match[i] := t;
end;
search := false;
end;
procedure km;
var
i, j, k, delta : longint;
begin
fillchar(match, sizeof(match), 0);
fillchar(lx, sizeof(lx), 0);
fillchar(ly, sizeof(ly), 0);
for i := 1 to n do
for j := 1 to n do
if (lx[i] < b[i, j]) or (lx[i] = 0) then
lx[i] := b[i, j];
for i := 1 to n do
repeat
fillchar(vx, sizeof(vx), 0);
fillchar(vy, sizeof(vy), 0);
if search(i) then break;
delta := maxlongint;
for j := 1 to n do
if vx[j] then
for k := 1 to n do
if not vy[k] then
if lx[j] + ly[k] - b[j, k] < delta then
delta := lx[j] + ly[k] - b[j, k];
for j := 1 to n do
if vx[j] then
lx[j] := lx[j] - delta;
for j := 1 to n do
if vy[j] then
ly[j] := ly[j] + delta;
until false;
end;
begin
readln(n);
for i := 1 to n do begin
for j := 1 to n do
read(a[i, j]);
readln;
end;
for i := 1 to n do
for j := 1 to n do
if i <> j then
for k := 1 to n do
b[i, k] := b[i, k] + a[j, k];
for i := 1 to n do
for j := 1 to n do
b[i, j] := -b[i, j];
km;
for i := 1 to n do
ans := ans + b[match[i], i];
writeln(-ans);
end.