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;
}