[APIO2015]雅加達的摩天樓

題目描述

印尼首都雅加達市有 NNN 座摩天樓,它們排列成一條直線,咱們從左到右依次將它們編號爲 000 到 $N − 1$ 。除了這 NNN 座摩天樓外,雅加達市沒有其餘摩天樓。ios

有 MMM 只叫作 「doge」 的神祕生物在雅加達市居住,它們的編號依次是 000 到 $M − 1$ 。編號爲 iii 的 doge 最初居住於編號爲 BiB_iBi​ 的摩天樓。每隻 doge 都有一種神祕的力量,使它們可以在摩天樓之間跳躍,編號爲 iii 的 doge 的跳躍能力爲 PiP_iPi​ ( Pi>0P_i > 0Pi​>0 )。測試

在一次跳躍中,位於摩天樓 bbb 而跳躍能力爲 ppp 的 doge 能夠跳躍到編號爲 $b − p$ (若是 $0 \leq b − p < N$ )或 b+pb + pb+p (若是 0≤b+p<N0 \leq b + p < N0≤b+p<N )的摩天樓。spa

編號爲 000 的 doge 是全部 doge 的首領,它有一條緊急的消息要儘快傳送給編code

號爲 111 的 doge。任何一個收到消息的 doge 有如下兩個選擇:blog

跳躍到其餘摩天樓上;ci

將消息傳遞給它當前所在的摩天樓上的其餘 doge。get

請幫助 doge 們計算將消息從 000 號 doge 傳遞到 111 號 doge 所須要的最少總跳躍步數,或者告訴它們消息永遠不可能傳遞到 111 號 doge。string

輸入輸出格式

輸入格式:

輸入的第一行包含兩個整數 NNN 和 MMM 。it

接下來 MMM 行,每行包含兩個整數 BiB_iBi​ 和 PiP_iPi​ 。io

輸出格式:

輸出一行,表示所須要的最少步數。若是消息永遠沒法傳遞到 111 號 doge,輸出 $−1$ 。

輸入輸出樣例

輸入樣例#1: 複製
5 3
0 2
1 1
4 1
輸出樣例#1: 複製
5

說明

【樣例解釋】

下面是一種步數爲 555 的解決方案:

000 號 doge 跳躍到 222 號摩天樓,再跳躍到 444 號摩天樓( 222 步)。

000 號 doge 將消息傳遞給 222 號 doge。

222 號 doge 跳躍到 333 號摩天樓,接着跳躍到 222 號摩天樓,再跳躍到 111 號摩天樓( 333 步)。

222 號 doge 將消息傳遞給 111 號 doge。

【數據範圍】

全部數據都保證 $0≤Bi<N0 \leq B_i < N0≤Bi​<N $。

子任務 1 (10 分) $1≤N≤101 \leq N \leq 101≤N≤10$

$1≤Pi≤101 \leq P_i \leq 101≤Pi​≤10$

$2≤M≤32 \leq M \leq 32≤M≤3$

子任務 2 (12 分)$1≤N≤1001 \leq N \leq 1001≤N≤100$

$1≤Pi≤1001 \leq P_i \leq 1001≤Pi​≤100$

$2≤M≤20002 \leq M \leq 20002≤M≤2000$

子任務 3 (14 分) $1≤N≤20001 \leq N \leq 20001≤N≤2000$

$1≤Pi≤20001 \leq P i ≤ 20001≤Pi≤2000$

$2≤M≤20002 \leq M \leq 20002≤M≤2000$

子任務 4 (21 分) $1≤N≤20001 \leq N \leq 20001≤N≤2000$

$1≤Pi≤20001 \leq P_i \leq 20001≤Pi​≤2000$

$2≤M≤300002 \leq M \leq 300002≤M≤30000$

子任務 5 (43 分) $1≤N≤300001 \leq N \leq 300001≤N≤30000$

$1≤Pi≤300001 \leq P_i \leq 300001≤Pi​≤30000$

$2≤M≤300002 \leq M \leq 300002≤M≤30000$

首先對於一個(i,p),若是暴力建邊,複雜度$O(mn)$

首先考慮分塊

若是p大於$n^{\frac{1}{2}}$那麼直接建邊$O(n^{\frac{1}{2}})$

若是p小於$n^{\frac{1}{2}}$

首先有一個思路就是設vis[i][p]表示是否考慮過(i,p)

這樣就不會重複建邊,邊數最多$m*n^{\frac{1}{2}}*log$

這樣簡單易懂,但空間卻不夠

若是不是捆綁測試就能拿不少分

因而轉化建邊思路,在p小於$n^{\frac{1}{2}}$

每一個點建$n^{\frac{1}{2}}$個輔助點,設爲<i,p>點

事先這樣建邊

1.給每一個<i,p>向$i$連邊,權爲0

2.給每一個<i,p>與<i+p,p>建雙向邊

若是有一個doge是(i,p)的,那麼

$i$連<i,p>,邊權爲0

這樣建邊保證跑最短路時從i跳到i+p,能夠直接從輔助點

並且保證了一個路徑必然是從有doge的地方出發的,否則根本到不了相應的輔助點

這樣邊數保證在$m*n^{\frac{1}{2}}$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;  8 struct Node  9 { 10   int next,to,dis; 11 }edge[30001*101*5]; 12 int dist[30001*101],lim,S,T,inf,head[30001*101],n,m,num,cnt; 13 bool vis[30001][101]; 14 queue<int>Q; 15 bool viss[30001*101]; 16 int get_id(int x,int y) 17 { 18   return y*n+x; 19 } 20 void add(int u,int v,int dis) 21 { 22   num++; 23   edge[num].next=head[u]; 24   head[u]=num; 25   edge[num].to=v; 26   edge[num].dis=dis; 27 } 28 void SPFA() 29 {int i; 30   memset(dist,127/3,sizeof(dist)); 31  Q.push(S); 32   inf=dist[0]; 33   memset(viss,0,sizeof(viss)); 34   dist[S]=0; 35   while (Q.empty()==0) 36  { 37       int u=Q.front(); 38  Q.pop(); 39       viss[u]=0; 40       for (i=head[u];i;i=edge[i].next) 41    { 42         int v=edge[i].to; 43         if (dist[v]>dist[u]+edge[i].dis) 44    { 45             dist[v]=dist[u]+edge[i].dis; 46             if (viss[v]==0) 47      { 48               viss[v]=1; 49      Q.push(v); 50      } 51    } 52    } 53  } 54 } 55 int main() 56 {int i,b,p,j; 57   cin>>n>>m; 58   lim=min((int)sqrt(n),100); 59   for (i=1;i<=n;i++) 60     for (j=1;j<=lim;j++) 61       add(get_id(i,j),i,0); 62   for (i=1;i<=n;i++) 63     for (j=1;j<=lim;j++) 64       if (i+j<=n) 65     add(get_id(i,j),get_id(i+j,j),1),add(get_id(i+j,j),get_id(i,j),1); 66   for (i=0;i<m;i++) 67  { 68       scanf("%d%d",&b,&p); 69       b++; 70       if (i==0) S=b; 71       if (i==1) T=b; 72       if (p>lim) 73       {cnt=0; 74         for (j=b;j+p<=n;j+=p) 75    { 76             add(b,j+p,++cnt); 77    } 78         cnt=0; 79         for (j=b;j-p>0;j-=p) 80    { 81             add(b,j-p,++cnt); 82    } 83    } 84       else
85    { 86         add(b,get_id(b,p),0); 87    } 88  } 89  SPFA(); 90   if (dist[T]==inf) cout<<-1; 91   else 
92   cout<<dist[T]; 93 }
相關文章
相關標籤/搜索