还是同一类最小割问题

对于只要记住,建图是来最小化损失,

最大化收益是所有收益-最小取不到的收益

首先对于每个经理i,如果不取,必然有signma(w[i,j])收益会得不到(这里我们先不考虑额外的损失);

如果取,必然会损失a[i](其实这个也不是收益,只是我们最后用sum-mincut时,sum不包括a[i],就相当于损失了);

下面考虑额外损失,对于i,j不在同一集合内(假设i被雇佣而j不被雇佣),会再损失2*w[i,j];

为什么是2倍呢,从建图来看,如果这样做最小割,雇佣i,不雇佣j,那么w[i,j]这个收益会被取到一次,而事实上不仅取不到还要额外损失,然后我们还要再减去一个经理之间的额外影响(由题意),所以是2倍;

然后分析完之后带入例子验证一下即可;

建图就不多说了

  1 const inf=2147483647;
  2 type node=record
  3        next,flow,point:longint;
  4      end;
  5 
  6 var edge:array[0..4400010] of node;
  7     d,p,cur,pre,h,numh:array[0..1010] of longint;
  8     t,len,n,m,i,j,x,s,ans:longint;
  9 
 10 function min(a,b:longint):longint;
 11   begin
 12     if a>b then exit(b) else exit(a);
 13   end;
 14 
 15 procedure add(x,y,f:longint);
 16   begin
 17     inc(len);
 18     edge[len].point:=y;
 19     edge[len].flow:=f;
 20     edge[len].next:=p[x];
 21     p[x]:=len;
 22   end;
 23 
 24 function sap:longint;
 25   var neck,i,j,tmp,u,q:longint;
 26   begin
 27     numh[0]:=t+1;
 28     sap:=0;
 29     neck:=inf;
 30     for i:=0 to t do
 31       cur[i]:=p[i];
 32     u:=0;
 33     while h[0]<t+1 do
 34     begin
 35       d[u]:=neck;
 36       i:=cur[u];
 37       while i<>-1 do
 38       begin
 39         j:=edge[i].point;
 40         if (edge[i].flow>0) and (h[u]=h[j]+1) then
 41         begin
 42           cur[u]:=i;
 43           pre[j]:=u;
 44           neck:=min(neck,edge[i].flow);
 45           u:=j;
 46           if u=t then
 47           begin
 48             while u<>0 do
 49             begin
 50               u:=pre[u];
 51               j:=cur[u];
 52               dec(edge[j].flow,neck);
 53               inc(edge[j xor 1].flow,neck);
 54             end;
 55             sap:=sap+neck;
 56             neck:=inf;
 57           end;
 58           break;
 59         end;
 60         i:=edge[i].next;
 61       end;
 62       if i=-1 then
 63       begin
 64         dec(numh[h[u]]);
 65         if numh[h[u]]=0 then exit;
 66         i:=p[u];
 67         tmp:=t;
 68         q:=-1;
 69         while i<>-1 do
 70         begin
 71           j:=edge[i].point;
 72           if (edge[i].flow>0) and (h[j]<tmp) then
 73           begin
 74             tmp:=h[j];
 75             q:=i;
 76           end;
 77           i:=edge[i].next;
 78         end;
 79         cur[u]:=q;
 80         h[u]:=tmp+1;
 81         inc(numh[h[u]]);
 82         if u<>0 then
 83         begin
 84           u:=pre[u];
 85           neck:=d[u];
 86         end;
 87       end;
 88     end;
 89   end;
 90 
 91 begin
 92   len:=-1;
 93   readln(n);
 94   fillchar(p,sizeof(p),255);
 95   t:=n+1;
 96   for i:=1 to n do
 97   begin
 98     read(x);
 99     add(i,t,x);
100     add(t,i,0);
101   end;
102   for i:=1 to n do
103   begin
104     s:=0;
105     for j:=1 to n do
106     begin
107       read(x);
108       s:=s+x;
109       if i<>j then
110       begin
111         add(i,j,x shl 1);
112         add(j,i,0);
113       end;
114     end;
115     add(0,i,s);
116     add(i,0,0);
117     ans:=ans+s;
118   end;
119   writeln(ans-sap);
120 end.
View Code

 

posted on 2014-07-06 17:52  acphile  阅读(159)  评论(0编辑  收藏  举报