P3645 [APIO2015]雅加达的摩天楼(BFS+根号平衡)
牛逼题,根本不用最短路,直接分析得出:
对于跳跃能力小于 (sqrt{n}) 的,可行的状态只有 (O(nsqrt{n})) 个。
对于跳跃能力大于 (sqrt{n}) 的,最多跳 (sqrt{n}) 次,所以可行的状态只有 (O(msqrt{n})) 个。
所以直接 (BFS) 一遍再判重即可,时间复杂度 (O(nsqrt{n})) ,用 (Map) 会 T 。
Map代码:
#include<bits/stdc++.h>
#define PII pair<int,int>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
const int N=1e5+5,M=105;
int n,m,dis[N],S,T;
bool vis[N];
struct node{
int b,p,step;
node(int b=0,int p=0,int step=0):b(b),p(p),step(step){}
};
map<PII,int> Map;
queue<node> q;
vector<int> vec[N];
void BFS(){
for(int i=0;i<vec[S].size();i++) q.push(node(S,vec[S][i],0)),Map[make_pair(S,vec[S][i])]=1;
while(!q.empty()){
node t=q.front();q.pop();
int pos=t.b,x=t.p,step=t.step;
if(dis[T]!=-1) break;
int w1=pos-x;
if(!Map[make_pair(w1,x)]||(w1>=0&&!vis[w1])){
if(w1>=0){
if(!vis[w1]){
vis[w1]=true;
for(int i=0;i<vec[w1].size();i++) q.push(node(w1,vec[w1][i],step+1)),Map[make_pair(w1,vec[w1][i])]=1;
}
q.push(node(w1,x,step+1));Map[make_pair(w1,x)]=1,dis[w1]=step+1;
}
}
int w2=pos+x;
if(!Map[make_pair(w2,x)]||(w2<n&&!vis[w2])){
if(w2>=n) continue;
if(!vis[w2]){
vis[w2]=true;
for(int i=0;i<vec[w2].size();i++) q.push(node(w2,vec[w2][i],step+1)),Map[make_pair(w2,vec[w2][i])]=1;
}
q.push(node(w2,x,step+1));Map[make_pair(w2,x)]=1,dis[w2]=step+1;
}
}
}
int main(){
read(n),read(m);
int u,v;read(u),read(v);q.push(node(u,v,0));S=u;
read(u),read(v);T=u;dis[T]=-1;vec[u].push_back(v);
for(int i=3;i<=m;i++) read(u),read(v),vec[u].push_back(v);
if(S==T){write(0);return 0;}
Map[make_pair(u,v)]=1;vis[S]=true,dis[S]=0;
BFS();
write(dis[T]);
return 0;
}