【BZOJ4152】【最短路】The Captain 题解

The Captain

给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。
Input
第一行包含一个正整数n(2<=n<=200000),表示点数。
接下来n行,每行包含两个整数x[i],yi,依次表示每个点的坐标。
Output
一个整数,即最小费用。
Sample Input
5
2 2
1 1
4 5
7 1
6 7
Sample Output
2
求出欧式距离,对于xy分别跑dijstra,如果SPFA要加堆优化。

/**
 * bzoj 4152 - B
 * Accepted
 * Author:lemonoil
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
#include <cctype>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <set>
#include <stack>
#include <vector>
#include <map>
#include <queue>
#include <list>
using namespace std;
const int N = 200005;
const int inf = 2100000000;
int n,k;
int xx[N],yy[N],d[N],tot,head[N];
struct edge{
    int to,w,next;
}e[N<<2];
struct data{
    int x,y;
    void read(){
        scanf("%d%d",&x,&y);
    }
}a[N<<2];
int cmpx(const int i,const int j){
    return a[i].x<a[j].x;
}
int cmpy(const int i,const int j){
    return a[i].y<a[j].y;
}
void addege(int x,int y,int z){
    e[++tot].next=head[x];e[tot].to=y;e[tot].w=z;head[x]=tot;
}
void add(int x,int y,int z){
    addege(x,y,z);addege(y,x,z);
}
struct node{
    int x,d;
    bool operator < (const node & rhs)const{
        return d>rhs.d;
    }
    node(){}
    node(int x,int d):x(x),d(d){}
};
priority_queue<node> Q;
void dijk(){
    for(int i=0;i<=n;i++)d[i]=inf;
    Q.push(node(0,0));d[0]=0;
    while(!Q.empty()){
        node t=Q.top();Q.pop();
        if(d[t.x]!=t.d)continue;
        for(int i=head[t.x];i;i=e[i].next){
            if(d[e[i].to]>d[t.x]+e[i].w){
                d[e[i].to]=d[t.x]+e[i].w;
                Q.push(node(e[i].to,d[e[i].to]));
            }
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        a[i].read();
        xx[i]=yy[i]=i;
    }
    sort(xx,xx+n,cmpx);
    for(int i=0;i<n-1;i++){
        data *x=a+xx[i],*y=a+xx[i+1];
        if((y->x-x->x)<=abs(x->y-y->y)){
            add(xx[i],xx[i+1],(y->x - x->x));
        }
    }
    sort(yy,yy+n,cmpy);
    for(int i=0;i<n-1;i++){
        data *x=a+yy[i],*y=a+yy[i+1];
        if((y->y-x->y)<=abs(x->x-y->x)){
            add(yy[i],yy[i+1],y->y - x->y);
        }
    }
    dijk();
    printf("%d\n",d[n-1]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值