aaa
The Captain
给定平面上的 \(n\) 个点,定义两点的距离为 \(\min(x_1-x_2,y_1-y_2)\),求从 \(1\sim n\) 的最小费用。
我们可以忽略 \(\min\),两个点分别建立 \(x,y\),肯定会走较小的边。然后我们对 \(x\) 排序,只需对相邻的点连边,那么不相邻的点之间的边权就恰好是它们之间的边权总和。对于 \(y\) 一样。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
const int N=200010,M=4*N;
int n;
int h[N],e[M],ne[M],idx,w[M];//don't forget memset h!
typedef long long ll;
ll dis[N];
bool st[N];
void Add(int a,int b,int c){
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void add(int a,int b,int c){
Add(a,b,c),Add(b,a,c);
}
struct Node{
int x;
ll dis;
bool operator<(const Node&A)const{
return dis>A.dis;
}
};
priority_queue<Node>q;
struct node{
int id,x,y;
}p[N];
bool cmp(node a,node b){
return a.x<b.x;
}
bool _cmp(node a,node b){
return a.y<b.y;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d",&n);
memset(h,-1,n*4+4);
E(i, n){
int x,y;
scanf("%d%d",&x,&y);
p[i]={i,x,y};
}
sort(p+1,p+1+n,cmp);
E(i, n-1)add(p[i].id,p[i+1].id,p[i+1].x-p[i].x);
sort(p+1,p+1+n,_cmp);
E(i, n-1)add(p[i].id,p[i+1].id,p[i+1].y-p[i].y);
memset(dis,0x3f,n*8+8);
q.push({1,0});
dis[1]=0;
while(!q.empty()){
auto t=q.top();q.pop();
int x=t.x,dist=t.dis;
if(x==n){
return printf("%d",dist),0;
}
if(st[x])continue;
st[x]=1;
Ed{
int j=e[i];
if(dis[j]>dist+w[i]){
dis[j]=dist+w[i];
q.push({j,dis[j]});
}
}
}
}