题意:
解法:
肯定是在1e5个点之间建图,
但是m2条显然不行。
考虑题目的传送性质:
紫色的两种路线是等价的,
简而言之:
当存在某个点,横坐标在其他两个点之间时,这个点可以作为转移的中间点,总路程不变。
纵坐标同理。
因此只需要对点按照横坐标排序,对相邻的点连边(纵坐标也连接一遍),
这样边的数量是O(m)的,之后直接最短路即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=2e5+5;
struct Node{
int x,y,id;
}p[maxm];
vector<PI>g[maxm];
int mark[maxm];
int dist[maxm];
int n,m;
bool cmp1(Node a,Node b){
return a.x<b.x;
}
bool cmp2(Node a,Node b){
return a.y<b.y;
}
void dj(int st){
priority_queue<PI,vector<PI>,greater<PI> >q;
for(int i=1;i<=m+2;i++){
dist[i]=1e18;
}
dist[st]=0;
q.push({dist[st],st});
while(!q.empty()){
int x=q.top().second;q.pop();
if(mark[x])continue;
mark[x]=1;
for(auto i:g[x]){
int v=i.first,w=i.second;
if(mark[v])continue;
if(dist[v]>dist[x]+w){
dist[v]=dist[x]+w;
q.push({dist[v],v});
}
}
}
}
int getd1(int i,int j){
return min(abs(p[i].x-p[j].x),abs(p[i].y-p[j].y));
}
int getd2(int i,int j){
return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);
}
signed main(){
cin>>n>>m;
cin>>p[m+1].x>>p[m+1].y;
cin>>p[m+2].x>>p[m+2].y;
for(int i=1;i<=m;i++){
cin>>p[i].x>>p[i].y;
p[i].id=i;
}
//
g[m+1].push_back({m+2,getd2(m+1,m+2)});
for(int i=1;i<=m;i++){
g[m+1].push_back({i,getd1(i,m+1)});
g[i].push_back({m+2,getd2(i,m+2)});
}
sort(p+1,p+1+m,cmp1);
for(int i=2;i<=m;i++){
int x=p[i].id,y=p[i-1].id;
g[x].push_back({y,getd1(i,i-1)});
g[y].push_back({x,getd1(i,i-1)});
}
sort(p+1,p+1+m,cmp2);
for(int i=2;i<=m;i++){
int x=p[i].id,y=p[i-1].id;
g[x].push_back({y,getd1(i,i-1)});
g[y].push_back({x,getd1(i,i-1)});
}
dj(m+1);
cout<<dist[m+2]<<endl;
return 0;
}