首页 > 代码库 > [SCOI2007] 修车

[SCOI2007] 修车

属于我的费用流版本终于诞生了!想来还有点小激动呢…看了下模板,之后完全按照自己的想象来写,这样在考场上也不怕啦~

某人说其实费用流就是把Dinic里的BFS换成SPFA,似乎还是比较有道理的,就是addflow要做一些修改,我第一次的错误就是addflow里的循环写成了while pre[x]<>st do,正解是while x<>st do。

既然算法的问题解决了,接下来的问题就是构图的问题——如何根据题目构建对应的网络。这一题的网络非常特殊,甚至被有些OIer评论为“非主流”…我理解别人的构图也花了一些时间…主要某一个点的费用是它对之后排着的顾客的影响。例如x点表示j号员工接手的倒数第k个顾客是顾客i,那么cost[x]=(k-1)*time[i,j],k映射成n-k就成为了我程序里的构图。在考前果断还要对各种构图熟悉一下,希望有时间。

program repair;type ptype=^node;     node=record          v,w,flow,cost:longint;          next,op:ptype;          end;const maxn=10000;var head,prep:array[0..maxn] of ptype;    visit:array[0..maxn] of boolean;    q,dis,pre:array[0..maxn] of longint;    time:array[0..100,0..100] of longint;    n,m,i,j,k,st,ed:longint;function min(a,b:longint):longint;begin  if a<b then exit(a) else exit(b);end;procedure insert(u,v,w1,w2,cost:longint);var p1,p2,q:ptype;begin  new(p1);  p1^.v:=v;p1^.w:=w1;p1^.flow:=0;p1^.cost:=cost;p1^.next:=nil;  q:=head[u];  if q=nil then head[u]:=p1 else    begin      q:=head[u];      head[u]:=p1;      p1^.next:=q;    end;  new(p2);  p2^.v:=u;p2^.w:=w2;p2^.flow:=0;p2^.cost:=-cost;p2^.next:=nil;  q:=head[v];  if q=nil then head[v]:=p2 else    begin      q:=head[v];      head[v]:=p2;      p2^.next:=q;    end;  p1^.op:=p2;p2^.op:=p1;end;function spfa:boolean;var star,rear,x:longint;    y:ptype;begin  fillchar(q,sizeof(q),0);  fillchar(pre,sizeof(pre),0);  fillchar(visit,sizeof(visit),false);  fillchar(dis,sizeof(dis),$7f);  star:=1;rear:=1;q[star]:=st;visit[st]:=true;dis[st]:=0;  while star<=rear do    begin      x:=q[star];      y:=head[x];      while y<>nil do        begin          if (dis[y^.v]>dis[x]+y^.cost) and (y^.w>y^.flow) then            begin              dis[y^.v]:=dis[x]+y^.cost;              pre[y^.v]:=x;              prep[y^.v]:=y;              if not visit[y^.v] then                begin                  inc(rear);                  q[rear]:=y^.v;                  visit[y^.v]:=true;                end;            end;          y:=y^.next;        end;      visit[x]:=false;      inc(star);    end;  spfa:=not (dis[ed]=2139062143);end;function addcost:longint;var x,addflow:longint;    y:ptype;begin  x:=ed;  addflow:=maxlongint;  while x<>st do    begin      y:=prep[x];      addflow:=min(addflow,y^.w-y^.flow);      x:=pre[x];    end;  x:=ed;  while x<>st do    begin      y:=prep[x];      inc(y^.flow,addflow);      dec(y^.op^.flow,addflow);      x:=pre[x];    end;  addcost:=addflow*dis[ed];end;function mincost:longint;begin  mincost:=0;  while spfa do inc(mincost,addcost);end;begin  //assign(input,repair.in);reset(input);  //assign(output,repair.out);rewrite(output);  readln(m,n);  st:=0;ed:=n+n*m+1;  for i:=1 to n do    for j:=1 to m do      read(time[i,j]);  for i:=1 to n do    insert(st,i,1,0,0);  for i:=n+n*m downto n+1 do    insert(i,ed,1,0,0);  for i:=1 to n do    for j:=1 to m do      for k:=1 to n do        insert(i,j*n+k,1,0,(n-k+1)*time[i,j]);  writeln(mincost/n:0:2);  //close(input);close(output);end.
repair

本题也是BZOJ 1070

啊啊啊还有2天就要坐灰机了,说来时间真的不多了。简单列一下还要复习的东西吧:树状数组/线段树,Splay(Ex.Cashier),KMP,Tarjan相关,并查集,二分匹配相关……好像也没时间搞别的了?~TAT~