BZOJ_4152

巧妙的性质:一个点最多只会与他横纵坐标最近的那4个点连边。所以我们sort sort连边建图。跑dijkstra

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <iostream>
 8 using namespace std;
 9 const int maxn = 200003;
10 int n;
11 int first[maxn],to[maxn*8],next[maxn*8],dis[maxn*8],eg;
12 inline void addedge(int x,int y,int d) {
13     next[++eg] = first[x];first[x] = eg;
14     to[eg] = y;dis[eg] = d;
15 }
16 inline void add(int x,int y,int d) {
17     addedge(x,y,d);
18     addedge(y,x,d);
19 }
20 struct Point {
21     int x,y,key;
22     void read() {
23         scanf("%d%d",&x,&y);
24     }
25 }dian[maxn];
26 bool cmp1(const Point& p,const Point& q) {
27     return p.x < q.x;
28 }
29 bool cmp2(const Point& p,const Point& q) {
30     return p.y < q.y;
31 }
32 struct rp {
33     int v,key;
34     rp(int _v = 0,int _key = 0) {
35         v = _v;key = _key;
36     }
37 };
38 struct cmp {
39     bool operator()(const rp& a,const rp& b) {
40         return a.v > b.v;
41     }
42 };
43 priority_queue<rp,vector<rp>,cmp>dui;
44 int dist[maxn];
45 bool vis[maxn];
46 inline void dijkstra(int u) {
47     memset(dist,0x3f,sizeof(dist));
48     dist[u] = 0;
49     rp a = rp(0,1);
50     dui.push(a);
51     while(!vis[n]) {
52         rp zxr_handsome = dui.top();
53         dui.pop();
54         if(vis[zxr_handsome.key]) continue;
55         vis[zxr_handsome.key] = 1;
56         for(int i = first[zxr_handsome.key];i;i = next[i]) {
57             int v = to[i];
58             int newdist = dist[zxr_handsome.key] + dis[i];
59             if(newdist < dist[v]) {
60                 dist[v] = newdist;
61                 dui.push(rp(newdist,v));
62             }
63         }
64     }
65     cout << dist[n] << endl;
66 }
67 int main() {
68     scanf("%d",&n);
69     for(int i = 1 ; i <= n ; ++i) dian[i].read(),dian[i].key = i;
70     sort(dian+1,dian+1+n,cmp1);
71     /*for(int i = 1 ; i <= n ; ++i) {
72         printf("%d ",dian[i].x);
73     }
74     cout << endl << endl;*/
75     for(int i = 2 ; i <= n ; ++i)
76         add(dian[i].key,dian[i-1].key,dian[i].x - dian[i-1].x);
77     sort(dian+1,dian+1+n,cmp2);
78     for(int i = 2 ; i <= n ; ++i)
79         add(dian[i].key,dian[i-1].key,dian[i].y - dian[i-1].y);
80     dijkstra(1);
81 }
View Code

然后据说这道题SPFA过不了,,我就过了一发。。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <iostream>
 8 using namespace std;
 9 const int maxn = 200003;
10 int n;
11 int first[maxn],to[maxn*8],next[maxn*8],dis[maxn*8],eg;
12 inline void addedge(int x,int y,int d) {
13     next[++eg] = first[x];first[x] = eg;
14     to[eg] = y;dis[eg] = d;
15 }
16 inline void add(int x,int y,int d) {
17     addedge(x,y,d);
18     addedge(y,x,d);
19 }
20 struct Point {
21     int x,y,key;
22     void read() {
23         scanf("%d%d",&x,&y);
24     }
25 }dian[maxn];
26 bool cmp1(const Point& p,const Point& q) {
27     return p.x < q.x;
28 }
29 bool cmp2(const Point& p,const Point& q) {
30     return p.y < q.y;
31 }
32 int dist[maxn];
33 bool ins[maxn];
34 inline void spfa(int u) {
35     deque<int>Q;
36     Q.push_front(u);
37     memset(dist,0x3f,sizeof(dist));
38     dist[u] = 0;
39     while(!Q.empty()) {
40         int u = Q.front();
41         Q.pop_front();
42         ins[u] = false;
43         for(int i = first[u];i;i = next[i]) {
44             int v = to[i];
45             int newdist = dist[u] + dis[i];
46             if(newdist < dist[v]) {
47                 dist[v] = newdist;
48                 if(!ins[v]) {
49                     if(Q.empty()) {
50                         Q.push_front(v);
51                     } else {
52                         int top = Q.front();
53                         if(dist[top] < dist[v]) Q.push_back(v);
54                         else Q.push_front(v);
55                     }
56                     ins[v] = 1;
57                 }
58             }
59         }
60     }
61     cout << dist[n];
62 }
63 int main() {
64     scanf("%d",&n);
65     for(int i = 1 ; i <= n ; ++i) dian[i].read(),dian[i].key = i;
66     sort(dian+1,dian+1+n,cmp1);
67     for(int i = 2 ; i <= n ; ++i)
68         add(dian[i].key,dian[i-1].key,dian[i].x - dian[i-1].x);
69     sort(dian+1,dian+1+n,cmp2);
70     for(int i = 2 ; i <= n ; ++i)
71         add(dian[i].key,dian[i-1].key,dian[i].y - dian[i-1].y);
72     spfa(1);
73 }
View Code

所以说双端队列就是好用。

原文地址:https://www.cnblogs.com/registerzxr/p/5081880.html