[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62834538

Description

给定平面上的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

自然是想到最短路,但一看数据范围,妈呀,吓傻了。dijkstra?o(n*n)的复杂度(当时还不知道有堆优化这东西),肯定TLE。用spfa,竟然也TLE了!?

首先是如何建边的问题,如果把所有的点都建边就太大了,空间都爆了。仔细看题,再画图一思考,即发现只需把x轴、y轴上相邻的的点连起来(明显比其他点优)。由此一来,每个点做多就连4条边。

然后就是算法的优化了。这道题卡spfa,明显摆明了要你用优化。dijktra或spfa都可以用堆优化,手打太麻烦,可以用STL里的优先队列(才学到,长知识了)。dijktra打丑了,一直wa,无可奈何只有改打spfa,结果一遍ac,spfa大法好!

坑点还是蛮多的,放在代码里面了

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
using namespace std; const int N=200000+5; int n;
int head[N],end[4*N],nxt[4*N],dis[4*N],hh=0;
struct Node{
int num,x,y;
}a[N];
ll dist[N];bool vis[N],con[N]; void adde(int a,int b,int di){
hh++;
end[hh]=b;
dis[hh]=di;
nxt[hh]=head[a];
head[a]=hh;
}
/*struct cmp{
bool operator()(int a,int b){
return dist[a]>dist[b];
}
};*/
bool cmp1(Node a,Node b){
return a.x<b.x;
}
bool cmp2(Node a,Node b){
return a.y<b.y;
}
int abs(int a){
return a<0?-a:a;
}
/*写wa了的dijkstra
ll dijkstra(int st,int en){
priority_queue<int,vector<int>,cmp> q;
memset(dist,0x3f,sizeof(dist));
dist[st]=0;
vis[st]=1;
con[st]=1;
q.push(st);
while(!q.empty()){
int u=q.top();q.pop();
con[u]=1;
if(u==en) break;
for(int i=head[u];i;i=nxt[i]){
int v=end[i],di=dis[i];//printf("%d ",v);
if(con[v]==1) continue;
if(dist[u]+(ll)di<dist[v]){
dist[v]=dist[u]+(ll)di;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
return dist[en];
}*/
ll spfa(int st,int en){
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;//优先队列(堆)
q.push(make_pair(0,st));
vis[st]=1;
dist[st]=0;
while(!q.empty()){
int u=q.top().second;
q.pop();//q是优先队列,后pop可能就不是u了
vis[u]=0;//还可能会被更新
for(int i=head[u];i;i=nxt[i]){
int v=end[i],di=dis[i];
if(dist[v]>dist[u]+di){
dist[v]=dist[u]+di;
if(!vis[v]){
q.push(make_pair(dist[v],v));
vis[v]=1;
}
}
}
}
return dist[en];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
a[i].num=i;
}
sort(a+1,a+n+1,cmp1);
for(int i=1;i<=n;i++){
if(i>1) adde(a[i].num,a[i-1].num,min(a[i].x-a[i-1].x,abs(a[i].y-a[i-1].y)));//建边要注意了,x轴上相邻的点可能y轴上的距离更近
if(i<n) adde(a[i].num,a[i+1].num,min(a[i+1].x-a[i].x,abs(a[i].y-a[i+1].y)));
}
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++){
if(i>1) adde(a[i].num,a[i-1].num,min(a[i].y-a[i-1].y,abs(a[i].x-a[i-1].x)));
if(i<n) adde(a[i].num,a[i+1].num,min(a[i+1].y-a[i].y,abs(a[i].x-a[i+1].x)));
}
printf("%lld",/*dijkstra(1,n)*/spfa(1,n));
return 0;
}

【bzoj4152】【The Captain】最短路(堆优化)(浅尝ACM-B)的更多相关文章

  1. $bzoj4152\ The\ Captain$ 最短路

    正解:最短路+优化连边 解题报告: 传送门$w$ 这种优化连边啥的真的好妙噢$QwQ$ 首先显然离散化下不说$QwQ$.然后对所有横坐标纵坐标分别建点,相邻两横坐标点相连,边权为离散前的坐标差.纵坐标 ...

  2. CCPC-Wannafly Winter Camp Day1 Div1 - 爬爬爬山 - [最短路][堆优化dijkstra]

    题目链接:https://zhixincode.com/contest/3/problem/F?problem_id=39 样例输入 1  4 5 1 1 2 3 4 1 2 1 1 3 1 1 4 ...

  3. [BZOJ1579] [Usaco2009 Feb]Revamping Trails 道路升级(分层图最短路 + 堆优化dijk)

    传送门 dis[i][j]表示第i个点,更新了j次的最短路 此题不良心,卡spfa #include <queue> #include <cstdio> #include &l ...

  4. LibreOJ #119. 最短路 (堆优化dijkstra)

    题目描述 给一个 n(1≤2500≤n) n(1 \leq 2500 \leq n)n(1≤2500≤n) 个点 m(1≤6200≤m) m(1 \leq 6200 \leq m)m(1≤6200≤m ...

  5. Codeforces Round #287 (Div. 2) E. Breaking Good 路径记录!!!+最短路+堆优化

    E. Breaking Good time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  6. HDU 2544 - 最短路 - [堆优化dijkstra][最短路模板题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 Time Limit: 5000/1000 MS (Java/Others) Memory Li ...

  7. 【bzoj4152】[AMPPZ2014]The Captain 堆优化Dijkstra

    题目描述 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. 输入 第一行包含一个正整数n(2<=n< ...

  8. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  9. Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路

    2834: 回家的路 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 62  Solved: 38[Submit][Status][Discuss] D ...

随机推荐

  1. JavaScript里面的面向对象

    1.JavaScript里面没有类,但是利用函数可以起到类似的作用,例如简单的构造方法,跟Python差别不大 function f1(mame,age){ this.Name = name; thi ...

  2. v-if与v-show区别

    在v-show中,元素是一直存在的,当v-show为false时,元素display:none只是隐藏了而已. v-if 作用:判断是否加载固定的内容,如果为真,则加载:为假时,则不加载. 用处:用在 ...

  3. CSS——(2)盒子模型与标准流

    上篇博客<CSS--(1)基础>中简单介绍了CSS的概念和几种使用方法,现在主要是介绍其的核心内容. 盒子模型 为了理解盒子模型,我们可以先从生活中的盒子入手.盒子是用来放置物品的,内部除 ...

  4. ubuntu16.04 使用问题笔记

    1.问题: 下列软件包有未满足的依赖关系: vim : 依赖: vim-common (= 2:7.4.826-1ubuntu1) 但是 2:7.4.1689-3ubuntu1 正要被安装 E: 无法 ...

  5. Linux下磁盘管理

    设置密码mkpasswdmkpasswd -s 0mkpasswd -s 0 -1 15 规定密码的长度 1. 查看磁盘或者目录的容量df 查看磁盘各分区使用情况 不加参数以k为单位 df -i in ...

  6. favicon.ico generator

    favicon.ico generator https://www.favicon-generator.org/ https://www.favicon.cc/ https://www.favicon ...

  7. P2294 [HNOI2005]狡猾的商人

    题目描述 输入输出格式 输入格式: 从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断.每组数据的第一行为两个正整数n和m, ...

  8. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  9. 《c程序设计语言》读书笔记-5.5-指针实现strncpy,strncat,strncmp

    #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> ...

  10. Linux下find命令参数及用法详解

    由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下.即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只你具有相应的权限.在运行一个非常 ...