【bzoj4152】【The Captain】最短路(堆优化)(浅尝ACM-B)
[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 Input5
2 2
1 1
4 5
7 1
6 7
Sample Output2
自然是想到最短路,但一看数据范围,妈呀,吓傻了。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)的更多相关文章
- $bzoj4152\ The\ Captain$ 最短路
正解:最短路+优化连边 解题报告: 传送门$w$ 这种优化连边啥的真的好妙噢$QwQ$ 首先显然离散化下不说$QwQ$.然后对所有横坐标纵坐标分别建点,相邻两横坐标点相连,边权为离散前的坐标差.纵坐标 ...
- 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 ...
- [BZOJ1579] [Usaco2009 Feb]Revamping Trails 道路升级(分层图最短路 + 堆优化dijk)
传送门 dis[i][j]表示第i个点,更新了j次的最短路 此题不良心,卡spfa #include <queue> #include <cstdio> #include &l ...
- 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 ...
- 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 ...
- HDU 2544 - 最短路 - [堆优化dijkstra][最短路模板题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 Time Limit: 5000/1000 MS (Java/Others) Memory Li ...
- 【bzoj4152】[AMPPZ2014]The Captain 堆优化Dijkstra
题目描述 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. 输入 第一行包含一个正整数n(2<=n< ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- Bzoj 2834: 回家的路 dijkstra,堆优化,分层图,最短路
2834: 回家的路 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 62 Solved: 38[Submit][Status][Discuss] D ...
随机推荐
- Rbac_权限管理
click!!! https://github.com/ugfly1210/rbac_100 有关于 rbac 的所有代码,包括 README. 用户和角色 : 多对多字段放在哪张表更好点? 用户找角 ...
- android桌面悬浮窗实现
首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. ...
- [洛谷P4149][IOI2011]Race
题目大意:给一棵树,每条边有边权.求一条简单路径,权值和等于$K$,且边的数量最小. 题解:点分治,考虑到这是最小值,不满足可减性,于是点分中的更新答案的地方计算重复的部分要做更改,就用一个数组记录前 ...
- 使用python读取mysql数据库并进行数据的操作
(一)环境的配置 使用python调用mysql数据库要引进一些库. 目前我使用的python版本是python3.6.引进库为pymysql 其他对应的库可以有以下选择: mysqldb,oursq ...
- 中英文混截,一个中文相当于n个英文
项目中遇到这么个需求,截取中英文字符串,一个中文相当于2个英文,全英文时截取12个英文字母,全中文时是6个中文汉字,中英文混合时是12个字节,在网上有找到这样的解决方案,但我没能静下心来研究懂,于是自 ...
- 安装PL/SQL Developer,链接本地64位Oracle
请参考: http://www.cnblogs.com/ymj126/p/3712727.html 或者 http://blog.csdn.net/cselmu9/article/details/80 ...
- HDU1556---树状数组 | 线段树 |*
输入n,紧接n行,每行a,b n个气球,a,b表示从第a到第b个气球涂一次色,输出每个球最终的涂几次色 暴力超时,优化数据结构 1.树状数组 #include<iostream> #inc ...
- Topcoder SRM548 Div 1
1. KingdomAndTrees 给出n个数a[1..n],求一个数组b[1..n]满足b严格递增,且b[1]>=1. 定义代价为W = max{abs(a[i]-b[i])},求代价最小值 ...
- Hibernate 中 get()和load()的区别
一.1.程序检索数据库中不存在的OID: load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 get方法检索不到的话会返回nu ...
- NEMA协议详解
NEMA协议的由来 NMEA协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marin ...