首页 > 代码库 > 【POJ3498】March of the Penguins(最大流,裂点)
【POJ3498】March of the Penguins(最大流,裂点)
题意:在靠近南极的某处,一些企鹅站在许多漂浮的冰块上。由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上。企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一个上限。
随着气温的升高,冰块开始融化,并出现了裂痕。而企鹅跳跃的压力,使得冰块的破裂加速。幸运的是,企鹅对冰块十分有研究,它们能知道每块冰块最多能承受多少次跳跃。对冰块的损害只在跳起的时候产生,而落地时并不对其产生伤害。
现在让你来帮助企鹅选择一个冰面使得它们可以聚集到一起。
第一行整数N,和浮点数D,表示冰块的数目和企鹅的最大跳跃距离。
(1≤N ≤100) (0 ≤D ≤100 000),
接下来N行,xi, yi, ni and mi,分别表示冰块的X和Y坐标,该冰块上的企鹅数目,以及还能承受起跳的次数。
输出所有可能的相聚冰块的编号,以0开始。如果不能相遇,输出-1。
思路:这道题是一年前上课最大流的例题,如果去年就拿了一等多好
考虑强行限制起跳次数很难,尝试裂点
将每块冰都裂成两个点(i,1),(i,2)
(i,1)-->(i,2)连流量为m[i]的边
对于原来在冰面上的企鹅,建立超级源S
s-->(i,1)连流量为n[i]的边
对于平面距离小于D的两点i,j
(i,2)-->(j,1)连流量为maxlongint的边
枚举(j,1)作为汇点判断最大流量是否>=企鹅总数即可
1 var head,vet,next,gap,dis,len,c,fan,a,b,save:array[0..100000]of longint; 2 x,y:array[1..100000]of double; 3 num:array[1..100000,1..2]of longint; 4 n,m,qq,tot,i,j,ans,v,cas,s,source,src,st:longint; 5 d:double; 6 7 procedure add(a,b,c:longint); 8 begin 9 inc(tot); 10 next[tot]:=head[a]; 11 vet[tot]:=b; 12 len[tot]:=c; 13 head[a]:=tot; 14 end; 15 16 function min(x,y:longint):longint; 17 begin 18 if x<y then exit(x); 19 exit(y); 20 end; 21 22 function dfs(u,aug:longint):longint; 23 var e,v,flow,t,val:longint; 24 begin 25 if u=src then exit(aug); 26 e:=head[u]; flow:=0; val:=s-1; 27 while e<>0 do 28 begin 29 v:=vet[e]; 30 if len[e]>0 then 31 begin 32 if dis[u]=dis[v]+1 then 33 begin 34 t:=dfs(v,min(len[e],aug-flow)); 35 len[e]:=len[e]-t; 36 len[fan[e]]:=len[fan[e]]+t; 37 flow:=flow+t; 38 if dis[source]>=s then exit(flow); 39 if aug=flow then break; 40 end; 41 val:=min(val,dis[v]); 42 end; 43 e:=next[e]; 44 end; 45 if flow=0 then 46 begin 47 dec(gap[dis[u]]); 48 if gap[dis[u]]=0 then dis[source]:=s; 49 dis[u]:=val+1; 50 inc(gap[dis[u]]); 51 end; 52 exit(flow); 53 end; 54 55 function maxflow:longint; 56 var ans:longint; 57 begin 58 fillchar(dis,sizeof(dis),0); 59 fillchar(gap,sizeof(gap),0); 60 gap[0]:=s; ans:=0; 61 while dis[source]<s do ans:=ans+dfs(source,maxlongint); 62 exit(ans); 63 end; 64 65 begin 66 assign(input,‘poj3498.in‘); reset(input); 67 assign(output,‘poj3498.out‘); rewrite(output); 68 readln(cas); 69 for v:=1 to cas do 70 begin 71 fillchar(head,sizeof(head),0); 72 tot:=0; qq:=0; s:=0; 73 read(n,d); 74 for i:=1 to n do 75 begin 76 read(x[i],y[i],a[i],b[i]); 77 qq:=qq+a[i]; 78 end; 79 for i:=1 to n do 80 begin 81 inc(s); num[i,1]:=s; 82 inc(s); num[i,2]:=s; 83 end; 84 inc(s); st:=s; 85 for i:=1 to n do 86 for j:=1 to n do 87 if (i<>j)and(sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]))<=d) then 88 begin 89 fan[tot+1]:=tot+2; 90 fan[tot+2]:=tot+1; 91 add(num[i,2],num[j,1],maxlongint); 92 add(num[j,1],num[i,2],0); 93 end; 94 for i:=1 to n do 95 begin 96 fan[tot+1]:=tot+2; 97 fan[tot+2]:=tot+1; 98 add(num[i,1],num[i,2],b[i]); 99 add(num[i,2],num[i,1],0); 100 end; 101 for i:=1 to n do 102 begin 103 fan[tot+1]:=tot+2; 104 fan[tot+2]:=tot+1; 105 add(st,num[i,1],a[i]); 106 add(num[i,1],st,0); 107 end; 108 source:=st; ans:=0; 109 for i:=1 to tot do save[i]:=len[i]; 110 for i:=1 to n do 111 begin 112 src:=num[i,1]; 113 if maxflow>=qq then 114 begin 115 inc(ans); c[ans]:=i; 116 end; 117 for j:=1 to tot do len[j]:=save[j]; 118 end; 119 if ans=0 then writeln(-1) 120 else 121 begin 122 for i:=1 to ans-1 do write(c[i]-1,‘ ‘); 123 write(c[ans]-1); 124 writeln; 125 end; 126 end; 127 close(input); 128 close(output); 129 end.
【POJ3498】March of the Penguins(最大流,裂点)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。