BZOJ 4070: [Apio2015]雅加达的摩天楼 根号分治+spfa
此题卡Dijkstra...
Code:
#include <bits/stdc++.h> #define N 30005 #define M 4000000 #define ll long long #define inf 100000000 #define E 14300000 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll d[M]; int n,m,block,cnt,edges,s,t; int id[N][103],hd[M],to[E],nex[E],val[E],done[M]; struct Node { int u; ll dis; Node(int u=0,ll dis=0):u(u),dis(dis){} bool operator<(Node b) const { return b.dis<dis; } }; priority_queue<Node>q; void add(int u,int v,int c) { // ++edges; nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c; } void Dijkstra() { memset(d,0x3f,sizeof(d)); for(d[s]=0,q.push(Node(s,0));!q.empty();) { Node e=q.top(); q.pop(); int u=e.u; if(done[u]) continue; done[u]=1; for(int i=hd[u];i;i=nex[i]) { int v=to[i]; if(d[v]>d[u]+val[i]) { d[v]=d[u]+val[i]; q.push(Node(v, d[v])); } } } } int main() { int i,j,k; // setIO("input"); scanf("%d%d",&n,&m); block=min(100,(int)sqrt(n)); cnt = n + 23; for(i=1;i<=block;++i) { for(j=0;j<i;++j) { for(k=j;k<n;k+=i) { id[k][i]=++cnt; add(cnt,k,0); if(k>=i) add(cnt-1,cnt,1), add(cnt,cnt-1,1); } } } for(i=1;i<=m;++i) { int a,b; scanf("%d%d",&a,&b); if(i==1) s=a; if(i==2) t=a; if(b<=block) add(a, id[a][b], 0); else { int tt=0; for(j=a-b;j>=0;j-=b) add(a,j,++tt); tt=0; for(j=a+b;j<n;j+=b) add(a,j,++tt); } } // printf("%d %d\n",cnt,edges); Dijkstra(); printf("%lld\n",d[t]>=inf?-1:d[t]); return 0; }