【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.
时间: 2024-10-27 03:24:40

【POJ3498】March of the Penguins(最大流,裂点)的相关文章

UVALive - 3972 March of the Penguins(最大流+枚举)

题目大意:有n个冰块,每块冰块能承受mi只企鹅从上面跳走 初始时每个冰块上有ai只企鹅,每只企鹅跳跃的最远距离为d,要求所有的企鹅在同一片冰块上集合,问哪些冰块满足要求 解题思路:这题和HDU - 2732 Leapin' Lizards 类似,具体的就不讲了,枚举+最大流就可以了 #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <c

UVA 12125 - March of the Penguins(最大流)

UVA 12125 - March of the Penguins 题目链接 题意:给定一些冰块,每个冰块上有一些企鹅,每个冰块有一个可以跳出的次数限制,每个冰块位于一个坐标,现在每个企鹅跳跃力为d,问所有企鹅能否跳到一点上,如果可以输出所有落脚冰块,如果没有方案就打印-1 思路:最大流,拆点表示冰块次数限制,然后枚举落脚冰块建图跑最大流即可 代码: #include <cstdio> #include <cstring> #include <queue> #inclu

uva 12125 March of the Penguins (最大流)

uva 12125 March of the Penguins 题目大意:网格上有n(n<=100)片荷叶,初始时第i片荷叶上有ni只企鹅(0<=ni<=10).由于承受能力有限,第i片荷叶最多只能承受mi(1<=mi<=200)只企鹅从上米娜跳走.一只企鹅最多能跳D(D<=105)单位距离.要求所有企鹅在同一片荷叶上集合.问哪些荷叶可以成为企鹅们集合的地点. 解题思路:企鹅为什么不游泳--.每片荷叶是有容量的,所以每片荷叶都要进行拆点,拆成两个点,容量为这片荷叶所能承

[POJ 3498] March of the Penguins

March of the Penguins Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 4378   Accepted: 1988 Description Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would l

poj 3498 March of the Penguins 点流量有限制的最大流

题意: 给n块浮冰的坐标,每块浮冰上的企鹅数和能承受跳起的次数,求有哪些浮冰能让企鹅能到一起. 分析: 拆点将点流量的限制转化为边流量的限制,求最大流. 代码: //poj 3498 //sep9 #include <iostream> #include <queue> #include <algorithm> #include <cmath> using namespace std; const int maxN=128; const int maxM=4

March of the Penguins

poj3498:http://poj.org/problem?id=3498 题意:某个冰块上有a只企鹅,总共可以跳出去b只,问是否可能所有的企鹅都跳到某一块冰块上,输出所有的可能的冰块的编号. 由于每个点只能跳出去m只企鹅,所以要拆点假如不拆点,一个点到另一个点可能会跳多于m只企鹅通过拆点后u->u'间的容量来完成题目的要求(对点的一些限制) 建图:i->i+n 容量为m i+n->j容量为INF新建源点s,s->i的容量为i点企鹅的个数然后枚举汇点求最大流就可以判断某个点是否符

hdu 2334 March of the Penguins

  题意大意 在X,Y坐标系中有N(N<=100)个冰块,有些冰块上有1若干只企鹅,每只企鹅一次最多跳M距离,一个冰块在有Mi个企鹅离开,就会消失,问有哪些冰块可以作为集合点,就是所有企鹅都能成功到这个冰块上来 题目分析  枚举点作为结束点,由于每个点有出企鹅的限制,用拆点来解决,一个点拆成"起点"和"终点",“起点"到"终点"的流量为最大离开企鹅数,而超级源点与每个点的"起点"做边,容量为其企鹅的数量,再根据

UVALIVE 3972 March of the Penguins

最大流建图比较容易第一次Dicnc抄了下别人的版 存一下以后方便查 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdi

POJ 3498 March of the Penguins(网络流+枚举)

题目链接:http://poj.org/problem?id=3498 题目: Description Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would like to get together, all on the same floe. The penguins do not wa