[AMPPZ2014] The Captain

问题描述

给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

输入格式

第一行包含一个正整数n(2<=n<=200000),表示点数。

接下来n行,每行包含两个整数x[i],y[i] (0<=x[i],y[i]<=10^9),依次表示每个点的坐标。

输出格式

一个整数,即最小费用。

样例输入

5
2 2
1 1
4 5
7 1
6 7

样例输出

2

解析

首先想到的应该是\(n^2\)连边,但显然不可行。接下来的任务就是尽量减少边的数量。可以发现,若以两点作为左上、右下角的矩形内有一点,那么两点之间的最短路一定是经过这个点的。所以,我们只需要依次按x和y坐标排序后连接相邻的两点,跑最短路即可。

注意此题卡SPFA。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define N 200002
#define M 400002
using namespace std;
struct point{
    int x,y,id;
}a[N];
int head[N],ver[M*2],nxt[M*2],edge[M*2],l;
int n,i,dis[N];
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
void insert(int x,int y,int z)
{
    l++;
    ver[l]=y;
    edge[l]=z;
    nxt[l]=head[x];
    head[x]=l;
}
int cmp1(const point &a,const point &b)
{
    return a.x<b.x;
}
int cmp2(const point &a,const point &b)
{
    return a.y<b.y;
}
void Dijkstra()
{
    priority_queue<pair<int,int> > q;
    memset(dis,0x3f,sizeof(dis));
    q.push(make_pair(0,1));
    dis[1]=0;
    while(!q.empty()){
        int x=q.top().second,d=-q.top().first;
        q.pop();
        if(dis[x]!=d) continue;
        for(int i=head[x];i;i=nxt[i]){
            int y=ver[i];
            if(dis[y]>d+edge[i]){
                dis[y]=d+edge[i];
                q.push(make_pair(-dis[y],y));
            }
        }
    }
}
int main()
{
    n=read();
    for(i=1;i<=n;i++){
        a[i].x=read(),a[i].y=read();
        a[i].id=i;
    }
    sort(a+1,a+n+1,cmp1);
    for(i=2;i<=n;i++){
        insert(a[i].id,a[i-1].id,a[i].x-a[i-1].x);
        insert(a[i-1].id,a[i].id,a[i].x-a[i-1].x);
    }
    sort(a+1,a+n+1,cmp2);
    for(i=2;i<=n;i++){
        insert(a[i].id,a[i-1].id,a[i].y-a[i-1].y);
        insert(a[i-1].id,a[i].id,a[i].y-a[i-1].y);
    }
    Dijkstra();
    cout<<dis[n]<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/LSlzf/p/11668916.html

时间: 2024-10-04 00:46:30

[AMPPZ2014] The Captain的相关文章

循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置: (3)当队列为空时,front与rear的值相等,但不一定为零: 3.循环队列入队的伪算法 (1)把值存在rear所在的位置: (2)rear=(rear+1)%maxsize ,其中maxsize代表数组的长度: 4.循环队列

BZOJ 4152: [AMPPZ2014]The Captain( 最短路 )

先按x排序, 然后只有相邻节点的边才有用, 我们连起来, 再按y排序做相同操作...然后就dijkstra ------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include

bzoj4152[AMPPZ2014]The Captain 最短路

4152: [AMPPZ2014]The Captain Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1517  Solved: 603[Submit][Status][Discuss] Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2<=n<=200000),表示点数. 接下来n行,每行包含

BZOJ4152: [AMPPZ2014]The Captain

Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2<=n<=200000),表示点数. 接下来n行,每行包含两个整数x[i],y[i](0<=x[i],y[i]<=10^9),依次表示每个点的坐标. Output 一个整数,即最小费用. Sample Input 5 2 2 1 1 4 5 7 1 6 7 Sample Output

【BZOJ】【4152】【AMPZZ2014】The Captain

最短路 题解:http://zyfzyf.is-programmer.com/posts/97953.html 按x坐标排序,相邻点之间连边.满足dist(x1,x3)<=dist(x1,x2)+dist(x2,x3)(因为可以走y) 再按y坐标排序,相邻点之间连边.同上 然而SPFA挂了……写了Dijkstra 1 /************************************************************** 2 Problem: 4152 3 User: Tu

BZOJ4152The Captain[DIjkstra]

4152: [AMPPZ2014]The Captain Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 700  Solved: 266[Submit][Status][Discuss] Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2<=n<=200000),表示点数. 接下来n行,每行包含两

AMPPZ2014

[AMPPZ2014]The Lawyer 记录每天结束的最早的会议以及开始的最晚的会议即可. #include<cstdio> #define N 500010 int n,m,i,d,a[N],b[N],st[21],en[21]; inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&am

浴谷夏令营题单

这是群里一位神犇整理的,我只负责将它们做完. 一.暴力.搜索Luogu 1588 丢失的牛Luogu 1463 [SDOI2005]反素数antBzoj 1085 [SCOI2005]骑士精神Luogu 1019 单词接龙Luogu 1078 文化之旅Luogu 1312 Mayan游戏Luogu 3823 蚯蚓排队Codeforces 444B Codeforces 555DLuogu 1979 华容道 二.初等数论Poj 3292 H合成数Luogu 1890 gcd区间Luogu 1029

bzoj4152

忘记优先队列初始是大根堆了.... 调了半天... 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #include<queue> 9 #include<vector>