首页 > 代码库 > 【Codevs1034】家园(最大流,裂点)

【Codevs1034】家园(最大流,裂点)

题意:由于人类对自然的疯狂破坏,人们意识到在大约2300年之后,地球不能再居住了,于是在月球上建立了新的绿地,以便在需要时移民。令人意想不到的是,2177年冬由于未知的原因,地球环境发生了连锁崩溃,人类必须在最短的时间内迁往月球。
现有n个太空站处于地球与月球之间(编号1..n),m艘公共交通太空船在其中来回穿梭,每个太空站Si可容纳无限的人,每艘太空船pi只可容纳Hpi人。对于每一艘太空船pi,将周期性地停靠一系列的太空站(Si1,Si2…Sir),如:(1,3,4)表示停靠太空站1 3 4 1 3 4 1 3 4 …。 任一艘太空船从任一个太空站驶往另一个任意的太空站耗时为1。人只能在太空船停靠太空站(或地球、月球)时上船或下船。初始时的人全在地球上,太空船全在初始站(太空船pi处于Si1),目标是让所有的人尽快地全部转移到月球上。

文件第一行为三个正整数 n(太空站个数)、 m(太空船个数)、 k(需要运送的地球上的人的个数),其中 1<=m<=13, 1<=n<=20, 1<=k<=50。

思路:按时间裂点跑最大流

num[i,j]表示i秒后的j点

(i,j)-->(i+1,j)连流量为无限边

(i,x)-->(i+1,y)连流量为h[k]的边,x,y为k号飞船分别在i,i+1时刻停留的星球

枚举答案并加边,dinic即可

注意每次最大流跑完后要把流量还原重构,改了很长时间没改出来

自己还是Too Simple

顺便说一句1999年的官方数据第二组是错的,正确答案是5,OUT是7

  1 var head,vet,next,len,dis,gap,fan,h,r,save:array[0..100000]of longint;
  2     a,b,num:array[0..110,0..110]of longint;
  3     n,m,i,j,k,x,ans,tot,source,src,s:longint;
  4 
  5 procedure add(a,b,c:longint);
  6 begin
  7  inc(tot);
  8  next[tot]:=head[a];
  9  vet[tot]:=b;
 10  len[tot]:=c;
 11  head[a]:=tot;
 12 end;
 13 
 14 function min(x,y:longint):longint;
 15 begin
 16  if x<y then exit(x);
 17  exit(y);
 18 end;
 19 
 20 function dfs(u,aug:longint):longint;
 21 var e,v,val,flow,t:longint;
 22 begin
 23  if u=src then exit(aug);
 24  flow:=0;
 25  e:=head[u]; val:=s-1;
 26  while e<>0 do
 27  begin
 28   v:=vet[e];
 29   if len[e]>0 then
 30   begin
 31    if dis[u]=dis[v]+1 then
 32    begin
 33     t:=dfs(v,min(len[e],aug-flow));
 34     len[e]:=len[e]-t;
 35     len[fan[e]]:=len[fan[e]]+t;
 36     flow:=flow+t;
 37     if dis[source]>=s then exit(flow);
 38     if aug=flow then break;
 39    end;
 40    val:=min(val,dis[v]);
 41   end;
 42   e:=next[e];
 43  end;
 44  if flow=0 then
 45  begin
 46   dec(gap[dis[u]]);
 47   if gap[dis[u]]=0 then dis[source]:=s;
 48   dis[u]:=val+1;
 49   inc(gap[dis[u]]);
 50  end;
 51  exit(flow);
 52 end;
 53 
 54 function maxflow:longint;
 55 var ans:longint;
 56 begin
 57  fillchar(dis,sizeof(dis),0);
 58  fillchar(gap,sizeof(gap),0);
 59  gap[0]:=s;
 60  ans:=0;
 61  while dis[source]<s do ans:=ans+dfs(source,maxlongint);
 62  exit(ans);
 63 end;
 64 
 65 begin
 66  assign(input,codevs1034.in); reset(input);
 67  assign(output,codevs1034.out); rewrite(output);
 68  readln(n,m,k);
 69  for i:=0 to 101 do
 70   for j:=1 to n+2 do
 71   begin
 72    inc(s); num[i,j]:=s;
 73   end;
 74  for i:=1 to m do
 75  begin
 76   read(h[i]); read(r[i]);
 77   for j:=1 to r[i] do
 78   begin
 79    read(a[i,j]);
 80    if a[i,j]=0 then a[i,j]:=n+1;
 81    if a[i,j]=-1 then a[i,j]:=n+2;
 82   end;
 83   x:=1; b[i,0]:=a[i,1];
 84   for j:=1 to 101 do
 85   begin
 86    inc(x); if x=r[i]+1 then x:=1;
 87    b[i,j]:=a[i,x];
 88   end;
 89 
 90  end;
 91  ans:=-1;
 92  source:=num[0,n+1];
 93 
 94  for i:=0 to 101 do
 95  begin
 96   for j:=1 to tot do save[j]:=len[j]; //重构边的容量,极其重要
 97   src:=num[i,n+2]; s:=src;
 98   if maxflow>=k then begin ans:=i; break; end;
 99   for j:=1 to tot do len[j]:=save[j]; //重构边的容量,极其重要
100   for j:=1 to m do
101   begin
102    fan[tot+1]:=tot+2;
103    fan[tot+2]:=tot+1;
104    add(num[i,b[j,i]],num[i+1,b[j,i+1]],h[j]);
105  //  writeln(i, ,b[j,i], ,i+1, ,b[j,i+1], ,h[j]);
106    add(num[i+1,b[j,i+1]],num[i,b[j,i]],0);
107   // writeln(i+1, ,b[j,i+1], ,i, ,b[j,i], ,0);
108   end;
109   for j:=1 to n+2 do
110   begin
111    fan[tot+1]:=tot+2;
112    fan[tot+2]:=tot+1;
113    add(num[i,j],num[i+1,j],maxlongint);
114   // writeln(i, ,j, ,i+1, ,j, ,maxlongint);
115    add(num[i+1,j],num[i,j],0);
116   // writeln(i+1, ,j, ,i, ,j, ,0);
117   end;
118   writeln;
119  end;
120  if ans>0 then writeln(ans)
121   else writeln(0);
122  //close(input);
123  //close(output);
124 end.

 

【Codevs1034】家园(最大流,裂点)