1. 程式人生 > >BZOJ4070: [Apio2015]雅加達的摩天樓

BZOJ4070: [Apio2015]雅加達的摩天樓

line tdi sky oid http using 關系 空間 struct

技術分享

思路{
  對於一條樓上的每一條狗.最直觀的方法是把一個點拆成N條狗的點,然後最短路即可。
  然而炸空間我也是醉了。
  因此我們要用到一個調調的分塊優化。
  應當是每個點的連通狀態。意會一下。
  把一座樓分成1-塊長層,那對於任意相同層數的狗可以在高空亂JB走。
  但連通長度p>塊長的呢?------直接連邊就可以了。
  然後YY一下,處理每條狗的激活關系。SPFA就可以了。
}

 

#include<bits/stdc++.h>
#define RG register
#define il inline 
#define N 5500000
#define Inf 2
#define U unsigned short
#define pos(i,j) (i*n+j)
using namespace std;
struct ed{int nxt,to,c;}e[30005*500];
int head[30005*105],dis[30005*105],n,m,q,b,s,t;bool in[30005*105];int tot;
void add(int u,int v,int c){e[tot].nxt=head[u];e[tot].to=v;e[tot].c=c;head[u]=tot++;}
void ADD(int u,int v,int c){add(u,v,c),add(v,u,c);}
void spfa(){
  queue<int>que;memset(dis,Inf,sizeof(dis));int SS=dis[t];
  que.push(s),in[s]=true,dis[s]=0;
  while(!que.empty()){
    int u=que.front();que.pop();in[u]=false;
    for(int i=head[u];i!=-1;i=e[i].nxt)if(dis[e[i].to]>dis[u]+e[i].c){
	int v=e[i].to;dis[v]=dis[u]+e[i].c;
	if(!in[v])que.push(v),in[v]=true;
      }
  }if(dis[t]==SS)cout<<"-1";
  else cout<<dis[t];
}
int main(){
  freopen("skyscraper.in","r",stdin);
  freopen("skyscraper.out","w",stdout);
  memset(head,-1,sizeof(head));
  cin>>n>>m;U int len=min((int)sqrt(n),100);
  for(RG int i=1;i<=len;++i)for(int j=1;j<=n;++j)add(pos(i,j),j,0);
  for(RG int i=1;i<=len;++i)for(int j=1;j<=n-i;++j)ADD(pos(i,j),pos(i,j+i),1);
  for(RG int i=1;i<=m;++i){int b,p;
    cin>>b>>p;b++;
    if(i==1)s=b;if(i==2)t=b;
    if(p<=len)add(b,pos(p,b),0);
    else {
      for(int j=1;j*p+b<=n;++j)add(b,b+j*p,j);
      for(int j=1;b-j*p>0;++j)add(b,b-j*p,j);
    }
  }spfa();
  return 0;
}

  

 

BZOJ4070: [Apio2015]雅加達的摩天樓