标签:
我们发现每次加入的边模p的余数是相同的,很容易想到对p分块O(3*n*sqrt(n)+2*num*sqrt(n)+(m-num))
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 30010 #define N 15000010 #define inf 1000000000 using namespace std; int head[110*maxn],to[N],len[N],next[N],dis[110*maxn]; bool vis[110*maxn]; int pos[110][maxn],q[110*maxn]; int n,m,num,block,cnt,s,t; void addedge(int x,int y,int z) { num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num; } void spfa() { for (int i=0;i<=cnt;i++) dis[i]=inf; int l=0,r=1; q[1]=s;vis[s]=1;dis[s]=0; while (l!=r) { l++;if (l==110*maxn) l=0; int x=q[l]; for (int p=head[x];p;p=next[p]) if (dis[x]+len[p]<dis[to[p]]) { dis[to[p]]=dis[x]+len[p]; if (!vis[to[p]]) { r++;if (r==110*maxn) r=0; vis[to[p]]=1;q[r]=to[p]; } } vis[x]=0; } } int main() { scanf("%d%d",&n,&m); cnt=n-1;block=min((int)sqrt(n),100); for (int i=1;i<=block;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-1,cnt,1),addedge(cnt,cnt-1,1); } for (int i=1;i<=m;i++) { int B,p; scanf("%d%d",&B,&p); if (i==1) s=B; if (i==2) t=B; if (p<=block) addedge(B,pos[p][B],0); else { for (int j=1;B+j*p<n;j++) addedge(B,B+j*p,j); for (int j=1;B-j*p>=0;j++) addedge(B,B-j*p,j); } } spfa(); if (dis[t]!=inf) printf("%d\n",dis[t]); else printf("-1\n"); return 0; }
【bzoj4070】[Apio2015]雅加达的摩天楼 分块+最短路
标签:
原文地址:http://blog.csdn.net/u012288458/article/details/51331034