4152: [AMPPZ2014]The Captain
Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 700 Solved: 266
[Submit][Status][Discuss]
Description
给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。
Input
第一行包含一个正整数n(2<=n<=200000),表示点数。
接下来n行,每行包含两个整数x[i],y[i](0<=x[i],y[i]<=10^9),依次表示每个点的坐标。
Output
一个整数,即最小费用。
Sample Input
5
2 2
1 1
4 5
7 1
6 7
2 2
1 1
4 5
7 1
6 7
Sample Output
2
HINT
Source
n2建边肯定不行
min可以无视掉,建两条边
假如两点之间有第三个点,那么只要分别和第三个点建边就行了,这两点之间不需要
- 所以每个点只需要向上下左右最靠近的点连边,排序即可
跑Dijkstra
// // main.cpp // bzoj4152thecaptain // // Created by Candy on 9/7/16. // Copyright © 2016 Candy. All rights reserved. // #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int N=200005,INF=1e9+5; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n; struct data{ int x,y,id; }p[N]; bool cmpx(data a,data b){ return a.x<b.x; } bool cmpy(data a,data b){ return a.y<b.y; } struct edge{ int v,w,ne; }e[N*4]; int h[N],cnt=0; void ins(int u,int v,int w){ cnt++; e[cnt].v=v;e[cnt].w=w;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].w=w;e[cnt].ne=h[v];h[v]=cnt; } void buildGraph(){ sort(p+1,p+1+n,cmpx); for(int i=1;i<=n-1;i++) ins(p[i].id,p[i+1].id,p[i+1].x-p[i].x); sort(p+1,p+1+n,cmpy); for(int i=1;i<=n-1;i++) ins(p[i].id,p[i+1].id,p[i+1].y-p[i].y); } struct hn{ int u,d; bool operator <(const hn &rhs)const{return d>rhs.d;} }; int d[N],done[N]; priority_queue<hn> q; void dijkstra(int s){ for(int i=1;i<=n;i++) d[i]=INF; d[s]=0;q.push((hn){s,0}); while(!q.empty()){ hn x=q.top();q.pop(); int u=x.u; if(done[u]) continue; done[u]=1; for(int i=h[u];i;i=e[i].ne){ int v=e[i].v; if(d[v]>d[u]+e[i].w){ d[v]=d[u]+e[i].w; q.push((hn){v,d[v]}); } } } } int main(int argc, const char * argv[]) { n=read(); for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read(),p[i].id=i; buildGraph(); dijkstra(1); printf("%d",d[n]); return 0; }