bzoj 2245 [SDOI2011]工作安排

来源:互联网 发布:联合国一票否决权 知乎 编辑:程序博客网 时间:2024/05/21 19:41

Description

你的公司接到了一批订单。订单要求你的公司提供n类产品,产品被编号为1~n,其中第i类产品共需要Ci件。公司共有m名员工,员工被编号为1~m员工能够制造的产品种类有所区别。一件产品必须完整地由一名员工制造,不可以由某名员工制造一部分配件后,再转交给另外一名员工继续进行制造。

我们用一个由01组成的m*n的矩阵A来描述每名员工能够制造哪些产品。矩阵的行和列分别被编号为1~m1~nAi,j1表示员工i能够制造产品j,为0表示员工i不能制造产品j

如果公司分配了过多工作给一名员工,这名员工会变得不高兴。我们用愤怒值来描述某名员工的心情状态。愤怒值越高,表示这名员工心情越不爽,愤怒值越低,表示这名员工心情越愉快。员工的愤怒值与他被安排制造的产品数量存在某函数关系,鉴于员工们的承受能力不同,不同员工之间的函数关系也是有所区别的。

对于员工i,他的愤怒值与产品数量之间的函数是一个Si+1段的分段函数。当他制造第1~Ti,1件产品时,每件产品会使他的愤怒值增加Wi,1,当他制造第Ti,1+1~Ti,2件产品时,每件产品会使他的愤怒值增加Wi,2……为描述方便,设Ti,0=0,Ti,si+1=+,那么当他制造第Ti,j-1+1~Ti,j件产品时,每件产品会使他的愤怒值增加Wi,j1jSi+1

你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小。由于我们并不想使用SpecialJudge,也为了使选手有更多的时间研究其他两道题目,你只需要输出最小的愤怒值之和就可以了。

Input

第一行包含两个正整数mn,分别表示员工数量和产品的种类数;

第二行包含n 个正整数,第i个正整数为Ci

以下m行每行n个整数描述矩阵A

下面m个部分,第i部分描述员工i的愤怒值与产品数量的函数关系。每一部分由三行组成:第一行为一个非负整数Si,第二行包含Si个正整数,其中第j个正整数为Ti,j,如果Si=0那么输入将不会留空行(即这一部分只由两行组成)。第三行包含Si+1个正整数,其中第j个正整数为Wi,j

 

Output

仅输出一个整数,表示最小的愤怒值之和。

 

Sample Input


2 3
2 2 2
1 1 0
0 0 1
1
2
1 10
1
2
1 6

Sample Output

24

Hint

w和t单调增。

 

 

规模不大。有工作“量”的限制。有极其类似费用的“愤怒值”。。。摆明了要考费用流的。。。

工作一边,人一边。

源向每个工作连边,流量即工程量,费用0。

每个工作向能承担这项工作的人连边,流量正无穷,费用0。

每个人向汇连边,流量分段,费用对应每个分段。

跑一遍zkw。

不得不说zkw的实效真是很出色的:

bzoj <wbr>2245 <wbr>[SDOI2011]工作安排

要知道。。以前我的代码从来都是垫底的。。。

 

今晚很nc地因为int64的问题调了好久。。。这样不行啊。。。会做的题目一定要保证时效啊!!!

 

ACCODE

program bzoj_2245;
const maxn=maxlongint;
var line,capa,cost,next:array[1..130000] of longint;
   hs,en,f,d,xx,yy:array[1..600] of longint;
   v,tt:array[1..600] of boolean;
   tot,n,s,t:longint;
   ans:int64;
//========================================================
procedure ins(x,y,z,h:longint);
begin
  inc(tot); line[tot]:=y;
  capa[tot]:=z; cost[tot]:=h;
  next[tot]:=en[x]; en[x]:=tot;
end;
//========================================================
procedure init;
var i,j,k,x,m,pre:longint;
begin
  readln(m,n);
  s:=n+m+1; t:=n+m+2; tot:=1;
  for i:=1 to n do
  begin
   read(x);
   ins(s,i,x,0);
   ins(i,s,0,0);
  end;
  for i:=1 to m do
    for j:=1 ton do
    begin
     read(x);
     if x=1 then
     begin
       ins(j,n+i,maxn,0);
       ins(n+i,j,0,0);
     end;
    end;
  for i:=1 to m do
  begin readln(k); pre:=0;
    for j:=1 tok do read(xx[j]);
    for j:=1 tok+1 do read(yy[j]);
    for j:=1 tok do
    begin
     ins(n+i,t,xx[j]-pre,yy[j]);
     ins(t,n+i,0,-yy[j]); pre:=xx[j];
    end;
   ins(n+i,t,maxn,yy[k+1]);
   ins(t,n+i,0,-yy[k+1]);
  end; n:=t;
end;
//========================================================
function dfs(u,flow:longint):longint;
var rest,l,tmp,i,vv:longint;
begin
  if u=t then
  begin
   ans:=ans+int64(flow*d[u]);
   exit(flow);
  end;
  v[u]:=false; tt[u]:=false;
  dfs:=0; i:=hs[u];
  while i<>0do
  begin
    vv:=line[i];l:=d[u]+cost[i]-d[vv];
   rest:=flow-dfs;
    ifcapa[i]<rest then rest:=capa[i];
    if(rest>0) and (l<f[vv]) thenf[vv]:=l;
    if(rest>0) and (l=0) and tt[vv] then
    begin
     tmp:=dfs(vv,rest);
     inc(dfs,tmp);
     dec(capa[i],tmp);
     inc(capa[i xor 1],tmp);
    end;
    if dfs=flowthen break;
    i:=next[i];hs[u]:=i;
  end; tt[u]:=true;
end;
//========================================================
procedure zkw;
var i,tmp,flow:longint;
begin
  ans:=0; flow:=0;
  fillchar(d,sizeof(d),0);
  fillchar(tt,sizeof(tt),true);
  repeat
    for i:=1 ton do hs[i]:=en[i];
    for i:=1 ton do v[i]:=true;
    for i:=1 ton do f[i]:=maxn;
   inc(flow,dfs(s,maxn));
   tmp:=maxn;
    for i:=1 ton do
     if (v[i]) and (f[i]<tmp) then tmp:=f[i];
    iftmp<>maxn then
     for i:=1 to n do
       if v[i] then inc(d[i],tmp);
  until tmp=maxn; writeln(ans);
end;
//========================================================
begin
  assign(input,'1.in'); reset(input);
  assign(output,'1.out'); rewrite(output);
  init;
  zkw;
  close(input); close(output);
end.

0 0