• bzoj 1497 最小割模型


    我们可以对于消费和盈利的点建立二分图,开始答案为所有的盈利和,

    那么源向消费的点连边,流量为消费值,盈利向汇连边,流量为盈利值

    中间盈利对应的消费连边,流量为INF,那么我们求这张图的最小割,用

    开始的答案减去最小割就是答案,因为最小割的存在不是左面就是右面,

    割左面,代表建这条路,需要对应的消费,那么割右面代表不要这项盈利,

    那本来加进去的盈利应该减掉,所以可以这样更新答案。

    /**************************************************************
        Problem: 1497
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:496 ms
        Memory:13116 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m                        :longint;
        pre, other, len             :array[0..1000010] of longint; 
        last                        :array[0..100010] of longint;
        l                           :longint;
        source, sink                :longint;
        ans                         :longint;
        que, d                      :array[0..100010] of longint;
         
    function min(a,b:longint):longint;
    begin
        if a>b then min:=b else min:=a;
    end;
     
    procedure connect(x,y,z:longint);
    begin
        inc(l);
        pre[l]:=last[x];
        last[x]:=l;
        other[l]:=y;
        len[l]:=z;
    end;
         
    procedure init;
    var
        i                           :longint;
        x, y, z                     :longint;
    begin
        read(n,m); source:=n+m+2; sink:=source+1;
        l:=1;
        for i:=1 to n do
        begin
            read(x);
            connect(source,i,x);
            connect(i,source,0);
        end;
        for i:=n+1 to n+m do
        begin
            read(x,y,z);
            connect(x,i,maxlongint div 10);
            connect(i,x,0);
            connect(y,i,maxlongint div 10);
            connect(i,y,0);
            connect(i,sink,z);
            connect(sink,i,0);
            ans:=ans+z;
        end;
    end;
     
    function bfs:boolean;
    var
        q, p, cur                   :longint;
        h, t                        :longint;
    begin
        fillchar(d,sizeof(d),0);
        h:=0; t:=1; d[source]:=1;
        que[1]:=source;
        while h<t do
        begin
            inc(h);
            cur:=que[h];
            q:=last[cur];
            while q<>0 do
            begin
                p:=other[q];
                if (len[q]>0) and (d[p]=0) then
                begin
                    inc(t);
                    que[t]:=p;
                    d[p]:=d[cur]+1;
                    if p=sink then exit(true);
                end;
                q:=pre[q];
            end;
        end;
        exit(false);
    end;
     
    function dinic(x,flow:longint):longint;
    var
        tmp, rest                   :longint;
        q, p                        :longint;
    begin
        if x=sink then exit(flow);
        rest:=flow;
        q:=last[x];
        while q<>0 do
        begin
            p:=other[q];
            if (len[q]>0) and (d[p]=d[x]+1) and (rest>0) then
            begin
                tmp:=dinic(p,min(len[q],rest));
                dec(rest,tmp);
                dec(len[q],tmp);
                inc(len[q xor 1],tmp);
            end;
            q:=pre[q];
        end;
        exit(flow-rest);
    end;
     
    procedure main;
    begin
        while bfs do ans:=ans-dinic(source,maxlongint div 10);
        writeln(ans);
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    [LeetCode] Wildcard Matching, Solution
    [LeetCode] Add Binary 解题报告
    [LeetCode] Validate Binary Search Tree 解题报告
    [LeetCode] ZigZag Conversion 解题报告
    [LeetCode] Best Time to Buy and Sell Stock II Solution
    [LeetCode] Anagrams 解题报告
    [LeetCode] Word Search 解题报告
    【转载】git/github初级运用自如
    关于实训的那点事儿
    【转载】解决git Push时请求username和password,而不是sshkey验证
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3496073.html
Copyright © 2020-2023  润新知