题目描述

印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N − 1。除了这 NN 座摩天楼外,雅加达市没有其他摩天楼。

有 M 只叫做 “doge” 的神秘生物在雅加达市居住,它们的编号依次是 0 到 M − 1。编号为 i 的 doge 最初居住于编号为 Bi​ 的摩天楼。每只 doge 都有一种神秘的力量,使它们能够在摩天楼之间跳跃,编号为 i 的 doge 的跳跃能力为 Pi​ (Pi​>0)。

在一次跳跃中,位于摩天楼 b 而跳跃能力为 p 的 doge 可以跳跃到编号为 b − p (如果 b − p < N)或 b+p(如果0≤b+p<N)的摩天楼。

编号为 0 的 doge 是所有 doge 的首领,它有一条紧急的消息要尽快传送给编

号为 1 的 doge。任何一个收到消息的 doge 有以下两个选择:

跳跃到其他摩天楼上;

将消息传递给它当前所在的摩天楼上的其他 doge。

请帮助 doge 们计算将消息从 0 号 doge 传递到 1 号 doge 所需要的最少总跳跃步数,或者告诉它们消息永远不可能传递到 1 号 doge。

输入输出格式

输入格式:

输入的第一行包含两个整数 N 和 M。

接下来 M 行,每行包含两个整数 Bi​ 和 Pi​。

输出格式:

输出一行,表示所需要的最少步数。如果消息永远无法传递到 1 号 doge,输出 −1。

输入输出样例

输入样例#1:

5 3
0 2
1 1
4 1
输出样例#1:

5

说明

【样例解释】

下面是一种步数为 5 的解决方案:

0 号 doge 跳跃到 2 号摩天楼,再跳跃到 4 号摩天楼(2 步)。

0 号 doge 将消息传递给 2 号 doge。

2 号 doge 跳跃到 3 号摩天楼,接着跳跃到 2 号摩天楼,再跳跃到 1 号摩天楼(3 步)。

2 号 doge 将消息传递给 1 号 doge。

【数据范围】

所有数据都保证 0≤Bi​<N。

子任务 1 (10 分)1≤N≤10

1≤Pi​≤10

2≤M≤3

子任务 2 (12 分)1≤N≤100

1≤Pi​≤100

2≤M≤2000

子任务 3 (14 分)1≤N≤2000

1≤P≤2000

2≤M≤2000

子任务 4 (21 分)1≤N≤2000

1≤Pi​≤2000

2≤M≤30000

子任务 5 (43 分)1≤N≤30000

1≤Pi​≤30000

2≤M≤30000

题解:

哇哇哇这道题A掉真不容易

这道题看到就想着建图,但是直接建肯定是不行的。

为啥不行呢?原来,对于某一个doge的p值,我们的建图方法是这样滴:

如果p值较大的话,那还好办,因为不会连出去多少边

但是,如果p值小的话,那么每一个点可能会往外连好多个边,而且可能有重复的!

复杂度可能接近 n² 哦

那么,如何改进建边方法?

老师教我们做分层图(似乎也叫分块?并不太清楚……)

对于p值较大的,比如大于sqrt(n)的,我们还直接建边

但是对于p值较小的,我们就对于不同的p值分别建图,然后每两个可一步到达的“相邻”点间都连正反两条边

就像这样:

p=1层的图:

p=2层的图:

(画图好累……)

好了大概层里建图就是这样

可是不能光在一个层里面跑啊,得在不同层间跑

那么不同层间的边怎么连?

不同层间的边其实就相当于一栋楼中有些可跳距离不同的doge,那对于每一个doge都把同一个点不同层的点指向该点(这样说好抽象啊……看代码应该好理解些)

这样建图复杂度是nlogn的

这样图建完后跑最短路就可以了

我一开始用dijkstra堆优化,但是始终T一个点。后来改成SPFA又修改了许多耗时的地方才A掉……95分了好长时间……

我做这道题时中间有一段时间一直65分,因为我在建图时有一块儿想错了

我把p值较大的暴力建图时是按照p值较小的建图方法建的(如上2图)

但是这样是有问题的

两者的区别不单是前者边少后者边多,更是前者只能从一个点出发去其他点,而后者可从每一个点出发去其他点!

虽然感觉上求两点之间距离这两种方法是一样的,但当有其他点、边或其他操作插进来后就很不一样了

比如前一个图,第三个点与第四个点是无法互相到达的,而在后面图中就可以

下次写题是一定要注意这一点!要想清楚了!

代码:

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#define INF 1000000007
using namespace std; const int MAXN = ;
struct node{
int v,len,lev;
node *next;
}pool[*MAXN],*h[][MAXN];
int cnt; int read(){
int x=,f=;
char ch=getchar();
while(ch>'' || ch<'') ch=getchar();
while(''<=ch && ch<='') x=x*+ch-'',ch=getchar();
return x;
} void addedge(int u,int lu,int v,int lv,int len){
node *p=&pool[++cnt];
p->v=v;p->len=len;p->lev=lv;
p->next=h[lu][u];h[lu][u]=p;
} int n,m,sn;
int b[MAXN],p[MAXN],vis[]; int d[][MAXN],use[][MAXN];
struct qqq{
int num,lev;
};
queue<qqq> que1;
void spfa(int S,int lS,int T){
int u,v,l;
qqq newq,now;
for(int i=;i<sn;i++)
for(int j=;j<n;j++) d[i][j]=INF;
while(!que1.empty()) que1.pop();
d[lS][S]=;
newq.num=S;newq.lev=lS;
que1.push(newq);
while(!que1.empty()){
now=que1.front();que1.pop();
u=now.num;l=now.lev;
for(node *p=h[l][u];p;p=p->next)
{
v=p->v;
if(d[p->lev][v]>d[l][u]+p->len){
d[p->lev][v]=d[l][u]+p->len;
if(use[p->lev][v]) continue;
newq.num=v;newq.lev=p->lev;
que1.push(newq);
use[p->lev][v]=;
}
}
use[l][u]=;
}
} int main()
{
int i,j,l2,S,T,lS;
n=read();m=read();
for(i=;i<m;i++) b[i]=read(),p[i]=read();
sn=min((int)sqrt(n),);
S=b[];T=b[];
if(p[]<sn) lS=p[];else lS=; //addedge
for(i=;i<m;i++){
if(p[i]>=sn){
vis[]=;
for(j=b[i]%p[i];j<n;j+=p[i]){
if(j==b[i]) continue;
addedge(b[i],,j,,abs(j-b[i])/p[i]);
}
}
else vis[p[i]]=;
}
for(i=;i<sn;i++)
if(vis[i]){
for(j=;j+i<n;j++){
addedge(j,i,j+i,i,);
addedge(j+i,i,j,i,);
}
}
//level
for(i=;i<m;i++){
if(p[i]<sn) l2=p[i];
else l2=;
for(j=;j<sn;j++)
if(j!=l2 && vis[j]){
addedge(b[i],j,b[i],l2,);
}
} //spfa
spfa(S,lS,T);
int ans=INF;
for(i=;i<sn;i++) ans=min(ans,d[i][T]);
if(ans==INF) printf("-1\n");
else printf("%d\n",ans); return ;
}

洛谷P3645 [APIO2015]雅加达的摩天楼的更多相关文章

  1. 洛谷P3645 [APIO2015]雅加达的摩天楼(最短路+分块)

    传送门 这最短路的建图怎么和网络流一样玄学…… 一个最朴素的想法是从每一个点向它能到达的所有点连边,边权为跳的次数,然后跑最短路(然而边数是$O(n^2)$除非自创复杂度比spfa和dijkstra还 ...

  2. 洛谷$P3645\ [APIO2015]$雅加达的摩天楼 最短路

    正解:最短路 解题报告: 传送门$QwQ$ 考虑暴力连边,发现最多有$n^2$条边.于是考虑分块 对于长度$p_i$小于等于$\sqrt(n)$的边,建立子图$d=p_i$.说下关于子图$d$的定义? ...

  3. 洛咕 P3645 [APIO2015]雅加达的摩天楼

    暴力连边可以每个bi向i+kdi连边权是k的边. 考虑这样的优化: 然后发现显然是不行的,因为可能还没有走到一个dog的建筑物就走了这个dog的边. 然后就有一个很妙的方法--建一个新的图,和原图分开 ...

  4. 【题解】P3645 [APIO2015]雅加达的摩天楼(分层图最短路)

    [题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是\(O(n^2)\)的过不去 然而我们有一个优化的办法,可以建一个新图\(G=( ...

  5. luogu P3645 [APIO2015]雅加达的摩天楼 分块 根号分治

    LINK:雅加达的摩天楼 容易想到设\(f_{i,j}\)表示第i个\(doge\)在第j层楼的最小步数. 转移显然是bfs.值得一提的是把初始某层的\(doge\)加入队列 然后转移边权全为1不需要 ...

  6. luogu P3645 [APIO2015]雅加达的摩天楼

    luogu 暴力? 暴力! 这个题有点像最短路,所以设\(f_{i,j}\)表示在\(i\)号楼,当前\(doge\)跳跃能力为\(j\)的最短步数,转移要么跳一步到\(f_{i+j,j}\)和\(f ...

  7. bzoj 4070 [Apio2015]雅加达的摩天楼 Dijkstra+建图

    [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 644  Solved: 238[Submit][Status][D ...

  8. 【BZOJ4070】[Apio2015]雅加达的摩天楼 set+最短路

    [BZOJ4070][Apio2015]雅加达的摩天楼 Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼 ...

  9. BZOJ 4070:[APIO2015]雅加达的摩天楼 最短路

    4070: [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 464  Solved: 164[Submit][Sta ...

随机推荐

  1. Linux 内核/sbin/hotplug 工具

    如同本章中前面提过的, 无论何时一个设备从系统中增删, 都产生一个"热插拔事件". 这 意味着内核调用用户空间程序 /sbin/hotplug. 这个程序典型地是一个非常小的 ba ...

  2. Linux 内核管理类

    一个类由一个 struct class 的实例来定义: struct class { char *name; struct class_attribute *class_attrs; struct c ...

  3. jQuery---鼠标滚轮控制div横向滚动条左右移动

    HTML <div class="table-responsive"> <div class="fhtable" style="wi ...

  4. C++ windows客户端支持SSL双向认证

    C++ windows客户端支持SSL双向认证,服务端是JAVA开发的,使用的证书是jks格式的.C++并不支持JKS格式的证书,所以要用openssl进行转换下. 1. 需要先把jks转成.p12文 ...

  5. (摘录)ISO C++ Lambda表达式

    ISO C++ 11 标准的一大亮点是引入Lambda表达式.基本语法如下: [捕获列表](形参列表) mutable ->返回值类型 复合语句 其中除了"[]"(其中捕获列 ...

  6. 【NOIP数据结构专项】单调队列单调栈

    [FZYZ P1280 ][NOIP福建夏令营]矩形覆盖 Description 有N个矩形,矩形的底边边长为1,且均在X轴上,高度给出,第i个矩形的高为h[i],求最少需要几个矩形才能覆盖这个图形. ...

  7. Qt3升至Qt4需要注意的几件事项浅谈

    Qt3升至Qt4需要注意的几件事项浅谈 公司以前的项目是用Qt3写的,随着时间的推移慢慢显示出Qt3有多方面的限制,因此先公司决定用Qt4来改写这个项目,并为软件添加新功能,在此背景先编写此文章. 先 ...

  8. Maven工程

    maven:父子工程 1,父工程并没有实质性的内容,所有的jar包都在里面,也就是说只需要管理jar包即可,不参与任务方法逻辑 2,在父工程中拥有很多的子模块,每一个子模块都代表了不用的包如(pack ...

  9. MFC_对话框_访问控件_7种方法_A

    访问对话框控件的七种方法 方法一. GetDlgItem()->GetWindowText(); GetDlgItem()->SetWindowText(); 方法二. GetDlgIte ...

  10. AI炼丹 - 深度学习必备库 numpy

    目录 深度学习必备库 - Numpy 1. 基础数据结构ndarray数组 1.1 为什么引入ndarray数组 1.2 如何创建ndarray数组 1.3 ndarray 数组的基本运算 1.4 n ...