zoukankan      html  css  js  c++  java
  • bzoj 2039 最小割模型

      比较明显的网络流最小割模型,对于这种模型我们需要先求获利的和,然后减去代价即可。

      我们对于第i个人来说, 如果选他,会耗费A[I]的代价,那么(source,i,a[i])代表选他之后的代价,如果不选他,我们会产生Σw[i][j] 1<=j<=n的代价,也就是这么多的利益我们无法得到,然后对于两个人的互相影响,连边(i,j,2*w[i][j]),代表如果不选i,选j的话,本来i中选j的利益得不到,又要损失j对i的影响为w[i][j]。所以共计损失2*w[i][j]。之后求最小割=最大流就行了。

    /**************************************************************
        Problem: 2039
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:860 ms
        Memory:47112 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n                           :longint;
        pre, other, len             :array[0..4000010] of longint;
        last                        :array[0..1010] of longint;
        l                           :longint;
        source, sink                :longint;
        que, d                      :array[0..1010] of longint;
        ans                         :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, j                        :longint;
        x                           :longint;
        sum                         :longint;
    begin
        read(n);
        source:=n+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:=1 to n do
        begin
            sum:=0;
            for j:=1 to n do
            begin
                read(x);
                if x=0 then continue;
                sum:=sum+x;
                connect(i,j,x<<1);
                connect(j,i,0);
                ans:=ans+x;
            end;
            connect(i,sink,sum);
            connect(sink,i,0);
        end;
    end;
     
    function bfs:boolean;
    var
        h, t, cur                   :longint;
        q, p                        :longint;
    begin
        fillchar(d,sizeof(d),0);
        h:=0; t:=1;
        que[1]:=source;
        d[source]:=1;
        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
        rest, tmp                   :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.
  • 相关阅读:
    矩阵特征值与特征向量
    拉格朗日插值matlab实现
    CloudCompare 的简单的使用说明
    kreuz-frankfurt-sample-generic-2019-02-08.xodr文件解读
    xml语言
    惯性坐标系
    四分位数及matlab实现
    参考文献类型标识
    matlab产生很多个相同的数字
    linux 中常用的一些头文件
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3514711.html
Copyright © 2011-2022 走看看