P3383: [Usaco2004 Open]Cave Cows 4 洞穴里的牛之四

这个系列总算是做完了,这是我第一次高效率做完四道题,虽然中间有两道水题,但是第一和第四题还是蛮好的,但是只要能想到思路就很快能打完的。

像这道题,刚开始在想能不能用DP?但是苦于不知道怎么实施,后来又想,这么多点,有点像最短路径,但是总共有50000个点,边数有可能N*N吗?

于是我拿起笔算了一下,发现连边的话,先按X轴由小到大排序一遍,然后往后找 X 比当前点大 <=2 的 X,再通过比较 Y 之间的关系,只要相差不超过 2 就连接一条双向边,这样后面的点就不需要往前找了,但有人会问,会不会是 50001*25000 而超时呢?我也想过,但是发现根本不可能,因为一个点最多能连接24条边,儿往后最多能找到14个点,也就是时间最多也就 50000*14 而事实上,这也是根本不可能达到的。所以我们连好边后做一遍 spfa 就行了。

 1 const maxn=50001;
 2 type
 3   node=record
 4     f,t:longint;
 5   end;
 6   position=record
 7     x,y:longint;
 8   end;
 9 var n,t,i,j,num,now,ans:longint;
10 b:array[0..750000] of node;
11 d,head:array[0..50001] of longint;
12 pos:array[0..50001] of position;
13 p:array[0..50001] of boolean;
14 f:array[0..5000000] of longint;
15 procedure qs(t,w:longint);
16 var l,r,mid:longint;
17 tem:position;
18 begin
19   l:=t; r:=w; mid:=pos[(l+r) shr 1].x;
20   repeat
21     begin
22       while pos[l].x<mid do inc(l);
23       while pos[r].x>mid do dec(r);
24       if l<=r then
25         begin
26           tem:=pos[l];
27           pos[l]:=pos[r];
28           pos[r]:=tem;
29           inc(l);
30           dec(r);
31         end;
32     end;
33   until l>r;
34   if t<r then qs(t,r);
35   if l<w then qs(l,w);
36 end;
37 procedure spfa;
38 var l,r,now,nowe:longint;
39 begin
40   fillchar(p,sizeof(p),true);
41   for l:=1 to n do d[l]:=maxn;
42   l:=1; r:=1; f[1]:=0; d[0]:=0; p[0]:=false;
43   while l<=r do
44     begin
45       now:=f[l];
46       nowe:=head[now];
47       while nowe<>0 do
48         begin
49            if d[now]+1<d[b[nowe].t] then
50              begin
51                d[b[nowe].t]:=d[now]+1;
52                if p[b[nowe].t] then
53                  begin
54                    p[b[nowe].t]:=false;
55                    inc(r);
56                    f[r]:=b[nowe].t;
57                  end;
58              end;
59            nowe:=b[nowe].f;
60         end;
61       inc(l);
62       p[now]:=true;
63     end;
64 end;
65 procedure insert(f,t:longint);
66 begin
67   inc(num);
68   b[num].f:=head[f];
69   b[num].t:=t;
70   head[f]:=num;
71 end;
72 begin
73   readln(n,t);
74   for i:=1 to n do
75     with pos[i] do readln(x,y);
76   qs(1,n);
77   pos[0].x:=0; pos[0].y:=0;
78   for i:=0 to n-1 do
79     begin
80       now:=i+1;
81       while (pos[now].x-pos[i].x<=2) and (now<=n) do
82         begin
83           if abs(pos[now].y-pos[i].y)<=2 then
84             begin
85               insert(i,now);
86               insert(now,i);
87             end;
88           inc(now);
89         end;
90     end;
91   spfa;
92   ans:=maxn;
93   for i:=1 to n do
94     if (ans>d[i]) and (pos[i].y=t) then ans:=d[i];
95   if ans<>maxn then writeln(ans)
96     else writeln(-1);
97 end.
View Code

   (转载请注明出处:http://www.cnblogs.com/Kalenda/)

posted @ 2015-09-23 12:51  LovelyMonster丶  阅读(329)  评论(0编辑  收藏  举报