巧妙的性质:一个点最多只会与他横纵坐标最近的那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 }
然后据说这道题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 }
所以说双端队列就是好用。