zoukankan      html  css  js  c++  java
  • 【Codevs1034&网络流24题】星际转移问题(最大流)

    题意:由于人类对自然的疯狂破坏,人们意识到在大约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.
  • 相关阅读:
    向存储过程中传入列表参数
    TRUNCATE TABLE (Transact-SQL)
    Program.cs
    联想G40-30 安装win10系统
    完美解决github访问速度慢[转]
    关于Visual studio 2017安装方法的若干问题
    [转载] 中国象棋软件-引擎实现(七)测试程序
    [转载] 中国象棋软件-引擎实现(六)局面评估
    [转载] 中国象棋软件-引擎实现(五)历史启发及着法排序
    [转载] 中国象棋软件-引擎实现(四)搜索算法
  • 原文地址:https://www.cnblogs.com/myx12345/p/6127052.html
Copyright © 2011-2022 走看看