[网络流][带点权边权图的转换][BZOJ 2039]人员雇佣

来源:互联网 发布:修改硬件信息软件 编辑:程序博客网 时间:2024/05/19 16:29

Description

作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司。这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j。当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得他的花费,那么作为一个聪明的人,小L当然不会雇佣他。 然而,那些没有被雇佣的人会被竞争对手所雇佣,这个时候那些人会对你雇佣的经理的工作造成影响,使得所赚得的利润减少Ei,j(注意:这里的Ei,j与上面的Ei,j 是同一个)。 作为一个效率优先的人,小L想雇佣一些人使得净利润最大。你可以帮助小L解决这个问题吗?

Analysis

嘛,这道题算是2007年国家队论文胡伯涛《最小割模型在信息学竞赛中的应用》的一个拓展运用吧。不过要注意的是一条边的权值被算了两次,还有算最小割时每条边的权值要乘个四...这里题目具体分析我不可能给得出。直接上代码吧...

var  n,vs,vt,edge,num,i,j,x,u,ans:longint;  e:array[1..1000000,1..3] of longint;  d,vd,fr,p,du:array[0..1010] of longint;procedure add(x,y,c:longint);begin  inc(edge); e[edge,1]:=y; e[edge,2]:=fr[x]; e[edge,3]:=c; fr[x]:=edge;end;function max(a,b:longint):longint;begin  if a>b then exit(a) else exit(b);end;function min(a,b:longint):longint;begin  if a<b then exit(a) else exit(b);end;function dfs(u,flow:longint):longint;var  k,tmp:longint;begin  if u=vt then exit(flow);  dfs:=0;  k:=fr[u];  while k<>0 do begin    if (e[k,3]>0) and (d[u]=d[e[k,1]]+1) then begin      tmp:=dfs(e[k,1],min(e[k,3],flow-dfs));      inc(dfs,tmp);      dec(e[k,3],tmp);      if odd(k) then inc(e[k+1,3],tmp) else inc(e[k-1,3],tmp);      if dfs=flow then exit;    end;    k:=e[k,2];  end;  dec(vd[d[u]]);  if vd[d[u]]=0 then d[vs]:=num;  inc(d[u]);  inc(vd[d[u]]);end;begin  readln(n);  vs:=0; vt:=n+1; num:=vt+1; vd[0]:=num;  for i:=1 to n do read(p[i]);  for i:=1 to n do begin    for j:=1 to n do begin      read(x);      if j<=i then continue;      inc(du[i],x+x); inc(du[j],x+x);      add(i,j,x+x+x+x);      add(j,i,x+x+x+x);    end;  end;  for i:=1 to n do u:=max(u,du[i]-2*p[i]);  for i:=1 to n do begin add(vs,i,u); add(i,vs,0); end;  for i:=1 to n do begin add(i,vt,u+2*p[i]-du[i]); add(vt,i,0); end;  while d[vs]<num do ans:=ans+dfs(vs,maxlongint);  ans:=(u*n-ans) div 2;  writeln(ans);end.