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.

posted @ 2009-01-04 12:18  jesonpeng  阅读(190)  评论(0编辑  收藏  举报