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 .

 

你可能感兴趣的:(ZOJ)