ex2.dpr

来自「tongji acm-online judge solution」· DPR 代码 · 共 231 行

DPR
231
字号
program Ural_1076(Input, Output);
const
    MaxN = 150+1;
    MaxNode = MaxN * 2 + 2;
    MaxEdge = (MaxN * MaxN +2 * MaxN) * 2;
    MaxValue = 32000;
type
    TIndex = Longint;
    TEdge = record
        Head, Tail, Cost:SmallInt;
	Capa, Flow:ShortInt;
	Index,Reverse:Word;
        Dirc: Boolean;
    end;
    TEdgeSet = array[1..MaxEdge] of TEdge;
    TEdgeFlag = array[0..MaxNode] of TIndex;
    TDistance = array[1..MaxNode] of TIndex;
    TThrough = array[1..MaxNode] of TIndex;
var
    NodeNum, EdgeNum: TIndex;
    Start, Termin: TIndex;
    Edge: TEdgeSet;
    H: TEdgeFlag;
    Dist: Tdistance;
    Through: TThrough;
    Total: TIndex;

function Compare(EA, EB: TEdge): TIndex;
var
    Res: TIndex;
begin
    Res := EA.Head - EB.Head;
    if Res = 0 then
        Res := EA.Tail - EB.Tail;
    if Res = 0 then
        Res := EA.Index - EB.Index;
    Compare := Res;
end;

procedure QuickSort(l, r: TIndex);
var
    i, j: TIndex;
    Mid, Tmp: TEdge;
begin
    i := l;
    j := r;
    Mid := Edge[(i + j) div 2];
    repeat
        while Compare(Edge[i], Mid) < 0 do
            Inc(i);
        while Compare(Mid, Edge[j]) < 0 do
            Dec(j);
        if i <= j then
        begin
            Tmp := Edge[i];
            Edge[i] := Edge[j];
            Edge[j] := Tmp;
            Inc(i);
            Dec(j);
        end;
    until i > j;
    if l < j then
        QuickSort(l, j);
    if i < r then
        QuickSort(i, r);
end;

function BinarySearch(Left, Right: TIndex; Key: TEdge): TIndex;
var
    Mid, Res: TIndex;
begin
    while Left <= Right do
    begin
        Mid := (Left + Right) div 2;
        Res := Compare(Edge[Mid], Key);
        if Res < 0 then
            Left := Mid + 1
        else if Res > 0 then
            Right := Mid - 1
        else
            Break;
    end;
    BinarySearch := (Left + Right) div 2;
end;

procedure InsertEdge(Head, Tail, Capa, Cost, Index: TIndex; Dirc: Boolean);
begin
    Inc(EdgeNum);
    Edge[EdgeNum].Head := Head;
    Edge[EdgeNum].Tail := Tail;
    Edge[EdgeNum].Capa := Capa;
    Edge[EdgeNum].Cost := Cost;
    Edge[EdgeNum].Flow := 0;
    Edge[EdgeNum].Index := Index;
    Edge[EdgeNum].Reverse := 0;
    Edge[EdgeNum].Dirc := Dirc;
    if Dirc then
        InsertEdge(Tail, Head, Capa, -Cost, Index, false);
end;

procedure Build_Network;
var
    i, j: TIndex;
    Len: TIndex;
    N: TIndex;
    Key: TEdge;
begin
    Readln(N);
    NodeNum := 2 * N + 2;
    Start := 1;
    Termin := 2 * N + 2;
    EdgeNum := 0;
    for i := 1 to N do
        for j := 1 to N do
        begin
            Read(Len);
            InsertEdge(i + 1, j + N + 1, 1, Len, (i - 1) * N + j, true);
            Inc(Total, Len);
        end;
    for i := 1 to N do
        InsertEdge(Start, i + 1, 1, 0, N * N + i, true);
    for i := 1 to N do
        InsertEdge(i + N + 1, Termin, 1, 0, N * N + N + i, true);

    QuickSort(1, EdgeNum);

    j := 0;
    H[0] := 0;
    for i := 1 to NodeNum do
    begin
        while (j + 1 <= EdgeNum) and (Edge[j + 1].Head = i) do
            Inc(j);
        H[i] := j;
    end;

    for i := 1 to EdgeNum do
        with Edge[i] do
            if Reverse = 0 then
            begin
                Key.Head := Tail;
                Key.Tail := Head;
                Key.Index := Index;
                Reverse := BinarySearch(H[Tail - 1] + 1, H[Tail], Key);
                Edge[Reverse].Reverse := i;
            end;
end;

function Bellman_Ford: Boolean;
var
    Times: TIndex;
    i: TIndex;
    Found: Boolean;
begin
    for i := 1 to NodeNum do
    begin
        Dist[i] := -MaxValue;
        Through[i] := -1;
    end;
    Dist[Start] := 0;
    Through[Start] := 0;
    Times := 0;
    repeat
        Inc(Times);
        Found := false;
        for i := 1 to EdgeNum do
            with Edge[i] do
                if ((Dirc and (Flow < Capa)) or (not Dirc and (Flow > 0)))
                    and (Through[Head] > -1) and (Dist[Head] + Cost > Dist[Tail])
                        then
                begin
                    Dist[Tail] := Dist[Head] + Cost;
                    Through[Tail] := i;
                    Found := true;
                end;
    until (Times = NodeNum - 1) or not Found;
    Bellman_Ford := (Through[Termin] > -1);
end;

procedure Ford_Fulkerson;
var
    i, u: TIndex;
begin
    repeat
        if not Bellman_Ford then
            Break;
        u := Termin;
        repeat
            if Through[u] = 0 then
                Break;
            with Edge[Through[u]] do
            begin
                if Dirc then
                begin
                    Inc(Flow);
                    Inc(Edge[Reverse].Flow);
                end
                else
                begin
                    Dec(Flow);
                    Dec(Edge[Reverse].Flow);
                end;
                u := Head;
            end;
        until false;
    until false;
    for i := 1 to EdgeNum do
        if Edge[i].Dirc and (Edge[i].Flow > 0) then
            Dec(Total, Edge[i].Flow * Edge[i].Cost);
    Writeln(Total);
end;

procedure Main;
begin
    Build_Network;
    Ford_Fulkerson;
end;
begin
{$IFNDEF ONLINE_JUDGE}
    Assign(Input, 'i.txt');
    Reset(Input);
    Assign(Output, 'o.txt');
    Rewrite(Output);
{$ENDIF}
    Main;
{$IFNDEF ONLINE_JUDGE}
    Close(Input);
    Close(Output);
{$ENDIF}
end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?