【BZOJ 4070】 [Apio2015]雅加达的摩天楼

4070: [Apio2015]雅加达的摩天楼

Time limit: 1000 ms

Memory limit: 262144 KB

Description

The city of Jakarta has N skyscrapers located on a line, conveniently numbered 0 through N-1 from left to right. There are no other skyscrapers in Jakarta.

Jakarta is inhabited by M mystical creatures called “doge”s. The doges are conveniently numbered 0 through M-1. Doge i initially resides in skyscraper Bi. Doge i has a mystical power, represented with a positive integer Pi. This mystical power enables doges to jump between skyscrapers. In a single jump, a doge with superpower p that is currently in skyscraper b can move to either skyscraper b+p (if 0 ≤ b+p < N) or skyscraper b-p (if 0 ≤ b-p < N).

Doge 0 is the most awesome doge, and it is the leader of all the doges. It has an urgent news for doge 1, and wants the news to reach doge 1 as quickly as possible. Any doge that has received the news can do any of the following actions:

Make a jump to move to some other skyscraper.

Pass the news to another doge in the same skyscraper.

Please help the doges by calculating the minimum number of total jumps required by all doges to pass the news to doge 1, or if it is impossible to do so.

Input Format

The first line contains two integers N and M. Each of the next M lines contains two integers Bi and Pi.

Output Format

A single line containing the minimum number of total jumps, or -1 if it is impossible.

Sample Input

5 3

0 2

1 1

4 1

Sample Output

5

Explanation

Here is one of the possible scenarios to pass the news using 5 jumps:

Doge 0 jumps to skyscraper 2 and then to skyscraper 4 (2 jumps).

Doge 0 passes the news to doge 2.

Doge 2 jumps to skyscraper 3, and then to skyscraper 2, and then to skyscraper 1 (3 jumps).

Doge 2 passes the news to doge 1.

Subtasks

For each subtask,

0 ≤ Bi < N

Subtask 1 (10 points)

1 ≤ N ≤ 10

1 ≤ Pi ≤ 10

2 ≤ M ≤ 3

Subtask 2 (12 points)

1 ≤ N ≤ 100

1 ≤ Pi ≤ 100

2 ≤ M ≤ 2,000

Subtask 3 (14 points)

1 ≤ N ≤ 2,000

1 ≤ Pi ≤ 2,000

2 ≤ M ≤ 2,000

Subtask 4 (21 points)

1 ≤ N ≤ 2,000

1 ≤ Pi ≤ 2,000

2 ≤ M ≤ 30,000

Subtask 5 (43 points)

1 ≤ N ≤ 30,000

1 ≤ Pi ≤ 30,000

2 ≤ M ≤ 30,000

分块+最短路。

这道题如果直接跑最短路,最坏可能会产生n2条边。

考虑分块:

①Pi>n ̄ ̄√

可以直接暴力来做,因为最多只会有nn ̄ ̄√条边

②Pi≤n ̄ ̄√

从每个点来看,最多只有n ̄ ̄√种走法,所以一共只有nn ̄ ̄√条边。

我们可以在后面添加一些辅助点来实现预处理:

枚举这≤n ̄ ̄√个长度,在后面分别建出n个辅助点,连向前面对应的位置,同时连向可以来自和到达的辅助点。

对于读入直接连向他对应的辅助点即可。

(详见代码)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#define M 30005
#define pb push_back
#define LL long long
using namespace std;
queue<int> q;
int B,tot=0,cnt,s,t,h[M*110],m,n,inq[M*110];
int d[M*110],pos[105][M];
struct data
{
    int b,p;
}a[M];
struct edge
{
    int y,ne,v;
}e[M*500];
void Addedge(int x,int y,int v)
{
    e[++tot].y=y;
    e[tot].v=v;
    e[tot].ne=h[x];
    h[x]=tot;
}
void SPFA()
{
    for (int i=0;i<=cnt;i++)
        d[i]=1e9,inq[i]=0;
    q.push(a[0].b);
    d[a[0].b]=0,inq[a[0].b]=1;
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        inq[x]=0;
        for (int i=h[x];i;i=e[i].ne)
        {
            int y=e[i].y;
            if (d[y]>d[x]+e[i].v)
            {
                d[y]=d[x]+e[i].v;
                if (!inq[y]) q.push(y),inq[y]=1;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=0;i<m;i++)
        scanf("%d%d",&a[i].b,&a[i].p);
    cnt=n-1;
    B=min((int)sqrt(n),100);
    for (int i=1;i<=B;i++)
        for (int j=0;j<i;j++)
            for (int k=j;k<n;k+=i)
            {
                pos[i][k]=++cnt;
                Addedge(cnt,k,0);
                if (k>=i)
                {
                    Addedge(cnt,cnt-1,1);
                    Addedge(cnt-1,cnt,1);
                }
            }
    for (int i=0;i<m;i++)
    {
        if (a[i].p<=B)
            Addedge(a[i].b,pos[a[i].p][a[i].b],0);
        else
        {
            for (int j=1;;j++)
                if (j*a[i].p+a[i].b>=n) break;
                else Addedge(a[i].b,j*a[i].p+a[i].b,j);
            for (int j=1;;j++)
                if (a[i].b-j*a[i].p<0) break;
                else Addedge(a[i].b,a[i].b-j*a[i].p,j);
        }
    }
    SPFA();
    if (d[a[1].b]==1e9)
        cout<<-1<<endl;
    else cout<<d[a[1].b]<<endl;
    return 0;
}

时间: 2024-11-10 01:26:09

【BZOJ 4070】 [Apio2015]雅加达的摩天楼的相关文章

BZOJ 4070: [Apio2015]雅加达的摩天楼

Descrption 有\(m\)只doge,每只doge只能到\(b_i+kp_i,k\in Z\),求0号doge将信息传给1号doge的最少跳跃步数.\(n\leqslant 3\times 10^4\) Solution 分块. 将\(p\)分成大于\(\sqrt n\)和小于等于\(\sqrt n\)的两部分,然后小于的部分可以暴力建好图再连边,大于的部分直接连所有能到达的位置即可. 复杂度\(O(n\sqrt n)\). PS:UOJ上过不了Extra Text... 其实时间复杂度

bzoj 4070: [Apio2015]雅加达的摩天楼【spfa】

明明是个最短路却有网络流一样的神建图= A = 首先要是暴力建图的话最坏有O(nm)条边.所以优化建图. 考虑分块思想,设bs=sqrt(n),对于p大于bs的,直接连边即可,最多有sqrt(n)条,注意边权不全是1了,因为要从b走过去:对于p小于等于bs,先把每栋楼建sqrt个辅助点,然后这些辅助点向原点连边,其中i点的辅助点j表示i栋楼可以跳p步.这些辅助点同层之间连双向边.然后对于一只狗,直接连接b点与b点的第p辅助点即可. spfa即可 然而事实证明bs取sqrt甚至会re,直接取100

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

[题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是$O(n^2)$的过不去 然而我们有一个优化的办法,可以建一个新图$G=(V,E)$其中$V$和原图$V$一一对应且连接一个$0$边,此外每个点向V中的$i+-d$连边. 类似网络流的办法瞎建就行了. 过不了uoj //@winlere #include<iostream> #include<cstdio> #include<cstring> #inc

BZOJ4070: [Apio2015]雅加达的摩天楼

思路{ 对于一条楼上的每一条狗.最直观的方法是把一个点拆成N条狗的点,然后最短路即可. 然而炸空间我也是醉了. 因此我们要用到一个调调的分块优化. 应当是每个点的连通状态.意会一下. 把一座楼分成1-块长层,那对于任意相同层数的狗可以在高空乱JB走. 但连通长度p>块长的呢?------直接连边就可以了. 然后YY一下,处理每条狗的激活关系.SPFA就可以了. } #include<bits/stdc++.h> #define RG register #define il inline

APIO2015 雅加达的摩天楼

首先可以看出这是一道求最短路的题目,但暴力建图最多n2 条边,所以考虑建图优化 对于p>sqrt(n) 的青蛙可以直接暴力建,最多n*sqrt(n) 条边 对于p<sqrt(n) 的青蛙添加辅助点,枚举这sqrt(n)个长度,每个长度建立n个辅助点前后对应连边,同时向它们可以到达的点以及可以到达它们的点连边 1 #define MAXN 4000010UL 2 #include <cstdio> 3 #include <queue> 4 #include <cma

【bzoj4070】[Apio2015]雅加达的摩天楼 分块+最短路

我们发现每次加入的边模p的余数是相同的,很容易想到对p分块 当p>sqrt(n)时,最多会连出O(sqrt(n))条边,直接连边即可 当p<=sqrt(n)时, 把图分成sqrt(n)+1层,最底层表示原来的节点 从下往上依次表示p=1.2.3--时的节点 对于每个p,把模p的余数相同的点顺次连接 对于每个读入的p,从最底层向对应的第p层的节点连一条权值为0的边即可 据说spfa快? 还算是道不错的题 O(3*n*sqrt(n)+2*num*sqrt(n)+(m-num)) #include&

UOJ111 APIO2015 雅加达的摩天楼 最短路、根号分治、bitset

传送门 70+Hack数据真是壮观~ 不难考虑到一个暴力的做法:设\(f_{i,j}\)表示在第\(i\)个点.从第\(j\)个doge跳过来的最短距离,因为边权为\(1\)所以就是个BFS,复杂度\(O(NM)\). 注意到可以优化一些状态:设\(f_{i,j}\)表示在第\(i\)个点.当前的doge的步长为\(j\)的方案数,然后再跑BFS. 看似这样还是\(O(N^2)\)的,但是实际复杂度变为了\(O(N\sqrt{N})\),复杂度分析考虑根号分治:当步长\(> \sqrt{N}\)

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

luogu 暴力? 暴力! 这个题有点像最短路,所以设\(f_{i,j}\)表示在\(i\)号楼,当前\(doge\)跳跃能力为\(j\)的最短步数,转移要么跳一步到\(f_{i+j,j}\)和\(f_{i-j,j}\),要么换到别的\(doge\),转移到\(f_{i,k}\) 这看似有\(n^2\)的状态,实际上状态数只有\(n\sqrt n\).因为当\(p> \sqrt n\)时,一个\(doge\)只能跳到\(\sqrt n\)个不同的点,这部分为\(m\sqrt n\);当\(p\l

bzoj4070【APIO2015】雅加达的摩天楼

4070: [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 189  Solved: 70 [Submit][Status][Discuss] Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N?1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 "doge" 的神秘生物在雅加达市居住,它们的编号依次是 0 到 M?