Codevs1034家园(最大流,裂点)
Posted myx12345
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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家园(最大流,裂点)的主要内容,如果未能解决你的问题,请参考以下文章