zoukankan      html  css  js  c++  java
  • 【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.
  • 相关阅读:
    HDU 5213 分块 容斥
    HDU 2298 三分
    HDU 5144 三分
    HDU 5145 分块 莫队
    HDU 3938 并查集
    HDU 3926 并查集 图同构简单判断 STL
    POJ 2431 优先队列
    HDU 1811 拓扑排序 并查集
    HDU 2685 GCD推导
    HDU 4496 并查集 逆向思维
  • 原文地址:https://www.cnblogs.com/myx12345/p/6127244.html
Copyright © 2011-2022 走看看