最短路好题,我们考虑两个点之间的直达路一定小于两个点之间加一个之后的拐弯路,于是分别按x、y排序建边即可,本题卡spfa。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#define maxn 200010
#define inf 1000000000000000000ll
#define pa pair<long long,int>
using namespace std;
struct yts
{
int x,y,id;
}a[maxn];
int to[4*maxn],next[4*maxn],head[maxn];
long long len[4*maxn],dis[maxn];
int n,num;
bool vis[maxn];
priority_queue<pa,vector<pa>,greater<pa> > q;
bool cmp(yts x,yts y)
{
return x.x<y.x;
}
bool cmp1(yts x,yts y)
{
return x.y<y.y;
}
void addedge(int x,int y,int z)
{
num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num;
}
void spfa()
{
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++) dis[i]=inf;
dis[1]=0;
q.push(make_pair(0,1));
while (!q.empty())
{
int x=q.top().second;q.pop();
if (vis[x]) continue;vis[x]=1;
for (int p=head[x];p;p=next[p])
if (dis[to[p]]>dis[x]+len[p])
{
dis[to[p]]=dis[x]+len[p];
q.push(make_pair(dis[to[p]],to[p]));
}
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for (int i=1;i<n;i++) addedge(a[i].id,a[i+1].id,a[i+1].x-a[i].x),addedge(a[i+1].id,a[i].id,a[i+1].x-a[i].x);
sort(a+1,a+n+1,cmp1);
for (int i=1;i<n;i++) addedge(a[i].id,a[i+1].id,a[i+1].y-a[i].y),addedge(a[i+1].id,a[i].id,a[i+1].y-a[i].y);
spfa();
printf("%lld\n",dis[n]);
return 0;
}