题目描述

印尼首都雅加达市有 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 安装一个中断处理

    如果你想实际地"看到"产生的中断, 向硬件设备写不足够; 一个软件处理必须在系统中配 置. 如果 Linux 内核还没有被告知来期待你的中断, 它简单地确认并忽略它. 中断线是一个 ...

  2. Linux 内核 NuBus 总线

    另一个有趣的, 但是几乎被忘记的, 接口总线是 NuBus. 它被发现于老的 Mac 计算机(那 些有 M68K CPU 家族的). 所有的这个总线是内存映射的(象 M68K 的所有东西), 并且设备 ...

  3. 文本框(代替input)输入长度限制、提示

    <div class="inform_content_text"> <textarea name="name" placeholder=&qu ...

  4. dotnet 通过 WMI 获取设备厂商

    本文告诉大家如何通过 WMI 获取设备厂商 通过 Win32_ComputerSystem 可以获取电脑系统信息 通过下面代码可以获取 机器型号 和 制造厂商 var mc = "Win32 ...

  5. java框架篇---Struts2 本地化/国际化(i18n)(转)

    源地址:https://www.cnblogs.com/oumyye/p/4368453.html 国际化(i18n)是规划和实施的产品和服务,使他们能很容易地适应特定的本地语言和文化的过程中,这个过 ...

  6. Perl 的内置变量$|

    $|是perl的内置变量,默认情况下是0,如果设置为非0的话,表示当前的输出不经过缓存立刻输出.相当于c语言的fflush()函数,立即刷新缓冲区. 比如你print或者write一个文件,实际是需要 ...

  7. Linux基础:CentOS 6重置密码

    1.开机,按"e"键,进入GNU GRUB引导界面,上下键选择中间行 2.按"e"键,进入编辑界面,末行quiet后空格,输入"1"或者&q ...

  8. django框架(2)

    cookie和session 1.cookie不属于http协议范围, 由于http协议无法保持状态, 但实际情况, 我们却又需要"保持状态",因此cookie就是在这样一个场景下 ...

  9. 为什么IIS应用程序池回收时间默认被设置为1740分钟?

    作者:斯科特 福赛斯/Scott Forsyth日期:2013/04/06地址:http://weblogs.asp.net/owscott/why-is-the-iis-default-app-po ...

  10. windows系统下的maven项目放到linux系统中运行时报org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnection这种异常的解决办法

    这个错误的解决办法其实很简单你把连接mysql数据库的那个jar包换成linux版本的就行了: linux版本的连接mysql数据库的jar包链接:http://files.cnblogs.com/f ...