【BZOJ4456】旅行者(最短路,分治)
2018-03-24 14:00
417 查看
题面
BZOJDescription
小Y来到了一个新的城市旅行。她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形成n×m个路口 (i,j)(1≤i≤n,1≤j≤m)。她发现不同的道路路况不同,所以通过不
同的路口需要不同的时间。通过调查发现,从路口(i,j)到路口(i,j+1)需要时间 r(i,j),从路口(i,j)到路口(i+1
,j)需要时间c(i,j)。注意这里的道路是双向的。小Y有q个询问,她想知道从路口(x1,y1)到路口(x2,y2)最少需要
花多少时间。
Input
第一行包含 2 个正整数n,m,表示城市的大小。接下来n行,每行包含m?1个整数,第i行第j个正整数表示从一个路口到另一个路口的时间r(i,j)。
接下来n?1行,每行包含m个整数,第i行第j个正整数表示从一个路口到另一个路口的时间c(i,j)。
接下来一行,包含1个正整数q,表示小Y的询问个数。
接下来q行,每行包含4个正整数 x1,y1,x2,y2,表示两个路口的位置。
Output
输出共q行,每行包含一个整数表示从一个路口到另一个路口最少需要花的时间。Sample Input
2 22
3
6 4
2
1 1 2 2
1 2 2 1
Sample Output
67
题解
ZJOI上讲得题目感觉很有意思
每次处理当前矩阵内的询问
将x,y两轴中较长的分成两半,使得矩阵尽可能“方”
如果一个询问的两个点跨越了这个中线,
则意味着答案一定经过了中线上的某个点
于是对中线上每个点跑一边对短路,
暴力更新答案
复杂度不会证明
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 111111 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } const int inf=100000000; int n,m,Q; int dis[MAX]; int X[MAX],Y[MAX],ans[MAX]; bool vis[MAX]; int bh(int i,int j){return i*m+j-m;} struct Line{int v,next,w;}e[200000]; int h[MAX],cnt=1; inline void Add(int u,int v,int w) { e[cnt]=(Line){v,h[u],w};h[u]=cnt++; e[cnt]=(Line){u,h[v],w};h[v]=cnt++; } struct Node{int i,dis;}; bool operator<(Node a,Node b){return a.dis>b.dis;} void Dijkstra(int S,int lx,int ly,int rx,int ry) { priority_queue<Node> Q; Q.push((Node){S,0}); for(int i=lx;i<=rx;++i) for(int j=ly;j<=ry;++j) dis[bh(i,j)]=inf,vis[bh(i,j)]=false; while(!Q.empty()) { int u=Q.top().i,D=Q.top().dis;Q.pop(); if(vis[u])continue;vis[u]=true; dis[u]=D; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(!vis[v]&&lx<=X[v]&&X[v]<=rx&&ly<=Y[v]&&Y[v]<=ry) Q.push((Node){v,dis[u]+e[i].w}); } } } struct Query{int id,u,v;}q[MAX],tmp[MAX]; void Work(int lx,int rx,int ly,int ry,int L,int R) { if(L>R)return; if(rx-lx>ry-ly) { int mid=(lx+rx)>>1; for(int i=ly;i<=ry;++i) { Dijkstra(bh(mid,i),lx,ly,rx,ry); for(int j=L;j<=R;++j) ans[q[j].id]=min(ans[q[j].id],dis[q[j].u]+dis[q[j].v]); } int cntl=L-1,cntr=R+1; for(int i=L;i<=R;++i) { int u=q[i].u,v=q[i].v; if(X[u]<mid&&X[v]<mid)tmp[++cntl]=q[i]; if(X[u]>mid&&X[v]>mid)tmp[--cntr]=q[i]; } for(int i=L;i<=R;++i)q[i]=tmp[i]; Work(lx,mid-1,ly,ry,L,cntl); Work(mid+1,rx,ly,ry,cntr,R); } else { int mid=(ly+ry)>>1; for(int i=lx;i<=rx;++i) { Dijkstra(bh(i,mid),lx,ly,rx,ry); for(int j=L;j<=R;++j) ans[q[j].id]=min(ans[q[j].id],dis[q[j].u]+dis[q[j].v]); } int cntl=L-1,cntr=R+1; for(int i=L;i<=R;++i) { int u=q[i].u,v=q[i].v; if(Y[u]<mid&&Y[v]<mid)tmp[++cntl]=q[i]; if(Y[u]>mid&&Y[v]>mid)tmp[--cntr]=q[i]; } for(int i=L;i<=R;++i)q[i]=tmp[i]; Work(lx,rx,ly,mid-1,L,cntl); Work(lx,rx,mid+1,ry,cntr,R); } } int main() { n=read();m=read(); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) X[bh(i,j)]=i,Y[bh(i,j)]=j; for(int i=1;i<=n;++i) for(int j=1;j<m;++j) Add(bh(i,j),bh(i,j+1),read()); for(int i=1;i<n;++i) for(int j=1;j<=m;++j) Add(bh(i,j),bh(i+1,j),read()); Q=read(); for(int i=1;i<=Q;++i) { int xa=read(),ya=read(),xb=read(),yb=read(); q[i]=(Query){i,bh(xa,ya),bh(xb,yb)}; } memset(ans,63,sizeof(ans)); Work(1,n,1,m,1,Q); for(int i=1;i<=Q;++i)printf("%d\n",ans[i]); return 0; }
相关文章推荐
- 【BZOJ4456】旅行者(最短路,分治)
- bzoj 4456: [Zjoi2016]旅行者 分治+最短路
- [分治 最短路] BZOJ 4456 [Zjoi2016]旅行者
- 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路
- 【BZOJ-4456】旅行者 分治 + 最短路
- bzoj4456 uoj184 ZJOI2016T2 旅行者 分治+最短路
- BZOJ4456 ZJOI2016旅行者(分治+最短路)
- 4456: [Zjoi2016]旅行者|分治+最短路
- 4456: [Zjoi2016]旅行者 分治+最短路
- [分治 + 最短路] BZOJ4456: [Zjoi2016]旅行者
- BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )
- 【BZOJ 4456】【UOJ #184】【ZJOI 2016】旅行者
- 【分治+最短路】UOJ#184【ZJOI2016】旅行者
- BZOJ 4016 最短路径树问题 [最短路+树分治]
- bzoj 4016: [FJOI2014]最短路径树问题 最短路+点分治
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
- [NEERC 2015] bzoj4449 Distance on Triangulation [分治+最短路]
- bzoj4456 [Zjoi2016]旅行者
- [BZOJ4449][Neerc2015][分治][最短路]Distance on Triangulation
- bzoj 4456: [Zjoi2016]旅行者