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]});
            }
        }
    }
}
posted @ 2023-08-29 08:07  wscqwq  阅读(5)  评论(0编辑  收藏  举报