本题可以用的方法很多,除去以下三种我所知道的就还有至少三种。
方法一:类似线段树优化建图,将一个平面等分成四份(若只有一行或一列则等分成两份),然后跑Dijkstra即可。建树是$O(n\log n)$的,单次连边是$O(n\log^2 n)$的。
1 #include<queue> 2 #include<vector> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 7 #define For(i,x) for (int i=h[x],k; i; i=nxt[i]) 8 using namespace std; 9 10 const int N=1000010,M=1500010; 11 struct E{ int w,l,r,u,d; }p[N]; 12 struct P{ int u,d; }; 13 vector<int>G[N]; 14 int n,m,W,H,now,dis,x,y,cnt,rt,tot,h[N],to[M],nxt[M],w[M],vis[N],d[N],ch[N][4]; 15 bool operator <(P x,P y){ return x.d>y.d; } 16 priority_queue<P>Q; 17 void add(int x,int y,int z){ to[++cnt]=y; nxt[cnt]=h[x]; w[cnt]=z; h[x]=cnt; } 18 19 void ins(int fa,int &k,int xl,int xr,int yl,int yr,int x,int y){ 20 if (x<xl||x>xr||y<yl||y>yr) return; 21 if (!k) k=++tot; 22 if (k!=rt) add(fa+n,k+n,0); 23 if (xl==xr&&yl==yr){ add(k+n,now,0); return; } 24 int xm=(xl+xr)>>1,ym=(yl+yr)>>1; 25 ins(k,ch[k][0],xl,xm,yl,ym,x,y); 26 ins(k,ch[k][1],xl,xm,ym+1,yr,x,y); 27 ins(k,ch[k][2],xm+1,xr,yl,ym,x,y); 28 ins(k,ch[k][3],xm+1,xr,ym+1,yr,x,y); 29 } 30 31 void link(int k,int xl,int xr,int yl,int yr,int xL,int xR,int yL,int yR){ 32 if (!k||xR<xl||xL>xr||yR<yl||yL>yr||d[k+n]<=dis) return; 33 if (xl>=xL&&xr<=xR&&yl>=yL&&yr<=yR){ d[k+n]=dis; Q.push((P){k+n,d[k+n]}); return; } 34 int xm=(xl+xr)>>1,ym=(yl+yr)>>1; 35 link(ch[k][0],xl,xm,yl,ym,xL,xR,yL,yR); 36 link(ch[k][1],xl,xm,ym+1,yr,xL,xR,yL,yR); 37 link(ch[k][2],xm+1,xr,yl,ym,xL,xR,yL,yR); 38 link(ch[k][3],xm+1,xr,ym+1,yr,xL,xR,yL,yR); 39 } 40 41 int main(){ 42 freopen("jump.in","r",stdin); 43 freopen("jump.out","w",stdout); 44 scanf("%d%d%d%d",&n,&m,&W,&H); 45 rep(i,1,n) scanf("%d%d",&x,&y),now=i,ins(0,rt,1,W,1,H,x,y); 46 rep(i,1,m) scanf("%d%d%d%d%d%d",&now,&p[i].w,&p[i].l,&p[i].r,&p[i].u,&p[i].d),G[now].push_back(i); 47 memset(d,63,sizeof(d)); d[1]=0; Q.push((P){1,0}); 48 while (!Q.empty()){ 49 int u=Q.top().u; Q.pop(); 50 if (vis[u]) continue; vis[u]=1; 51 for (int i=0;i<(int)G[u].size();i++) 52 x=G[u][i],dis=d[u]+p[x].w,link(rt,1,W,1,H,p[x].l,p[x].r,p[x].u,p[x].d); 53 For(i,u) if (d[k=to[i]]>d[u]+w[i]) Q.push((P){k,d[k]=d[u]+w[i]}); 54 } 55 rep(i,2,n) printf("%d\n",d[i]); 56 return 0; 57 }