给出
n
≤
2
e
5
n\leq2e5
n≤2e5个点,每个点的坐标是
0
−
1
e
9
0-1e9
0−1e9范围的,然后两个点之间的费用是
m
i
n
{
∣
x
1
−
x
2
∣
,
∣
y
1
−
y
2
∣
}
min\{|x_1-x_2|,|y_1-y_2|\}
min{∣x1−x2∣,∣y1−y2∣},求从点
1
1
1到点
n
n
n的最短路的距离。
最暴力的做法就是在任意两点之间连上权值。考虑建图优化,不必两两之间连上边,而是利用传递性连边。我们可以同时连上
∣
x
1
−
x
2
∣
|x_1-x_2|
∣x1−x2∣和
∣
y
1
−
y
2
∣
|y_1-y_2|
∣y1−y2∣,然后分别按照
x
x
x,
y
y
y顺序排序,然后依次连边。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2e5+7;
struct Point{
int x,y;
int id;
}a[N];
bool cmp1(Point a,Point b) {
if(a.x<b.x) return 1;
else if(a.x==b.x&&a.y<b.y) return 1;
else return 0;
}
bool cmp2(Point a,Point b) {
if(a.y<b.y) return 1;
else if(a.y==b.y&&a.x<b.x) return 1;
else return 0;
}
struct edge{ int v; ll w; };
vector<edge> G[N];
void add(int u,int v,ll w) {
G[u].push_back({v,w});
G[v].push_back({u,w});
}
struct node{
int u;
ll dis;
bool operator <(const node &rhs) const {
return dis>rhs.dis;
}
};
priority_queue<node> q;
ll dis[N];
bool vis[N];
int n;
ll solve() {
for(int i=1;i<=n;i++)
dis[i]=1e15;
dis[1]=0;
q.push({1,dis[1]});
while(!q.empty()) {
node cur=q.top();
q.pop();
int u=cur.u;
if(vis[u]) continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++) {
int v=G[u][i].v;
ll w=G[u][i].w;
if(dis[v]>dis[u]+w) {
dis[v]=dis[u]+w;
q.push({v,dis[v]});
}
}
}
return dis[n];
}
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+1+n,cmp1);
for(int i=1;i<n;i++) {
add(a[i].id,a[i+1].id,abs(a[i].x-a[i+1].x));
}
sort(a+1,a+1+n,cmp2);
for(int i=1;i<n;i++) {
add(a[i].id,a[i+1].id,abs(a[i].y-a[i+1].y));
}
ll ans=solve();
printf("%lld\n",ans);
return 0;
}