题目描述

印尼首都雅加达市有 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. sqlyog提示:没有执行查询。请在 SQL 窗口中输入查询或将光标放在一个查询上。

    以下内容纯属猜测: sqlyog 在执行输入的sql语句时,对已经执行过的语句,是不会再执行的,所以出现这个问题,很可能是sql语句没有修改,就试图执行第二遍.

  2. XSS攻击及防范

    1.什么是XSS攻击 跨站脚本攻击(Cross Site Scripting),攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到 ...

  3. Java 学习笔记(4)——面向对象

    现在一般的语言都支持面向对象,而java更是将其做到很过分的地步,java是强制使用面向对象的写法,简单的写一个Hello Word都必须使用面向对象,这也是当初我很反感它的一点,当然现在也是很不喜欢 ...

  4. HDU1166 敌兵布阵 BZOJ1012 最大数[树状数组]

    一.前置知识-树状数组 树状数组(binary indexed tree)是一种简洁的代码量很小的数据结构,能够高效的处理前缀区间上的问题.在很多情况下能写树状数组解决的就不用码半天线段树了. 树状数 ...

  5. poj3471 - 倍增+LCA+树上差分

    题意:一张n节点连通无向图,n-1条树边,m条非树边.若通过先删一条树边,再删一条非树边想操作 将此图划分为不连通的两部分,问有多少种方案. 利用LCA整好区间覆盖,dfs用来求前缀和 需要注意的是, ...

  6. 使用svndumpfilter exclude来清理svn库的废弃文件实现差别备份

      先啰嗦下为什么要使用svndumpfilter… svn库用久了以后就会越来越大,进行整体文件打包备份的时候,发现压力山大…尤其是美术团队也在使用svn进行重要美术资源管理的时候…….几百g的资源 ...

  7. Java入门(三)——集合概讲

    集合(或者叫容器)是Java的核心知识点,它有着很深的深度.我们这里不会设计多深,仅仅作为了解入门,深入了解请移步各种集合源码文章.好的,下面正是开始介绍... Java集合为何而生 我们知道,Jav ...

  8. SpringBoot原理分析与配置

    1.1 起步依赖原理分析 1.1.1 分析spring-boot-starter-parent 按住Ctrl点击pom.xml中的spring-boot-starter-parent,跳转到了spri ...

  9. 在nginx里面部署node.js本地服务器

    我一个前端,为啥要搞服务器呢?因为公司就招了一个后端啊,后端忙不过来,就叫我这个萌新前端去搞后端的东西,我太难了. 直接进入正题吧,因为公司需求,要我在nginx服务器上面搭一个node.js服务器, ...

  10. 20行Python代码爬取王者荣耀全英雄皮肤

    引言王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了.我们今天的重点是爬取王者荣耀所有英雄的所有皮肤,而且仅仅使用20行Python代码即可完成. 准备工作 ...