【考试题】坠短路
【问题描述】
给定平面上的 n 个点,定义(x1,y1)到(x2,y2)的费用为 min(|x1-x2|,|y1-y2|),求从 1 号点
走到 n 号点的最小费用。
【输入】
第一行包含一个正整数 n(2<=n<=200000),表示点数。
接下来 n 行,每行包含两个整数 x[i],yi,依次表示每个点的坐标。
【输出】
一个整数,即最小费用。
网上有相似的题目吧。 = =
考场上floyd水了30.
考后wdz一句话就说明白了?
按x坐标排序,再按y坐标排序,跑dij K Stra。
就是先按x坐标排序,然后顺次联边,对y也这么搞一搞。
然而wdz的std用的是Super-FAST
SPFA秒之= =
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<queue>
#define Fname "dist"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;bool flg=0;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return flg?-x:x;
}
const int maxn=200010;
int n;
struct d{int x,y,id;}s[maxn];
il bool cmp_x(const d&a,const d&b){return a.x<b.x;}
il bool cmp_y(const d&a,const d&b){return a.y<b.y;}
int fir[maxn],dis[maxn<<2],nxt[maxn<<2],w[maxn<<2],id;
il vd _add(int a,int b,int c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
il vd add(int a,int b,int c){_add(a,b,c),_add(b,a,c);}
ll dist[maxn];
int que[maxn],hd,tl;
bool inque[maxn];
int main(){
freopen(Fname".in","r",stdin);
freopen(Fname".out","w",stdout);
n=gi();
rep(i,1,n)s[i].x=gi(),s[i].y=gi(),s[i].id=i;
sort(s+1,s+n+1,cmp_x);
rep(i,2,n)add(s[i-1].id,s[i].id,s[i].x-s[i-1].x);
sort(s+1,s+n+1,cmp_y);
rep(i,2,n)add(s[i-1].id,s[i].id,s[i].y-s[i-1].y);
dist[1]=0;rep(i,2,n)dist[i]=1e15;
que[tl++]=1;inque[1]=1;
int x;
while(hd^tl){
x=que[hd];
erep(i,x)
if(dist[dis[i]]>w[i]+dist[x]){
dist[dis[i]]=w[i]+dist[x];
if(!inque[dis[i]])que[tl++]=dis[i],tl%=maxn;
}
inque[x]=0;++hd,hd%=maxn;
}printf("%lld
",dist[n]);
return 0;
}