4456: [Zjoi2016]旅行者|分治+最短路
2016-04-18 15:13
477 查看
每次将矩形划分成两个部分,枚举中间点跑最短路更新答案,不断递归分治
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<ctime> #include<set> #include<map> #define N 200020 #define M 200050 #define inf 1e9 #define pa pair<int,int> using namespace std; int sc() { int i=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i; } struct W{int x1,x2,y1,y2,p;}a[M],b[M]; int head ,nxt[N<<1],lst[N<<1],v[N<<1]; int px ,py ,mark ,dis ,ans[M]; int n,m,tot,Q; void insert(int x,int y,int z) { lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; v[tot]=z; lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot; v[tot]=z; } inline int get(int x,int y) { return (x-1)*m+y; } priority_queue<pa,vector<pa>,greater<pa> >q; inline bool jud(int x,int nl,int nr,int ml,int mr) { if(px[x]<nl||px[x]>nr)return 0; if(py[x]<ml||py[x]>mr)return 0; return 1; } void dijkstra(int x,int nl,int nr,int ml,int mr) { for(int i=nl;i<=nr;i++) for(int j=ml;j<=mr;j++) { int p=get(i,j); dis[p]=1e9; mark[p]=0; } q.push(make_pair(dis[x]=0,x)); while(!q.empty()) { int x=q.top().second;q.pop(); if(mark[x])continue;mark[x]=1; for(int i=head[x];i;i=nxt[i]) if(dis[x]+v[i]<dis[lst[i]]&&jud(lst[i],nl,nr,ml,mr)) q.push(make_pair(dis[lst[i]]=dis[x]+v[i],lst[i])); } } void solve(int nl,int nr,int ml,int mr,int ql,int qr) { //cout<<nl<<" "<<nr<<" "<<ml<<" "<<mr<<" "<<ql<<" "<<qr<<endl; if(ql>qr)return; if(nr-nl>mr-ml) { int mid=nl+nr>>1; for(int i=ml;i<=mr;i++) { dijkstra(get(mid,i),nl,nr,ml,mr); for(int j=ql;j<=qr;j++) ans[a[j].p]=min(ans[a[j].p],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]); } int l=ql-1,r=qr+1; for(int i=ql;i<=qr;i++) if(a[i].x1<mid&&a[i].x2<mid) b[++l]=a[i]; else if(a[i].x1>mid&&a[i].x2>mid) b[--r]=a[i]; for(int i=ql;i<=l;i++) a[i]=b[i]; for(int i=qr;i>=r;i--) a[i]=b[i]; solve(nl,mid-1,ml,mr,ql,l); solve(mid+1,nr,ml,mr,r,qr); } else { int mid=ml+mr>>1; for(int i=nl;i<=nr;i++) { dijkstra(get(i,mid),nl,nr,ml,mr); for(int j=ql;j<=qr;j++) ans[a[j].p]=min(ans[a[j].p],dis[get(a[j].x1,a[j].y1)]+dis[get(a[j].x2,a[j].y2)]); } int l=ql-1,r=qr+1; for(int i=ql;i<=qr;i++) if(a[i].y1<mid&&a[i].y2<mid) b[++l]=a[i]; else if(a[i].y1>mid&&a[i].y2>mid) b[--r]=a[i]; for(int i=ql;i<=l;i++) a[i]=b[i]; for(int i=qr;i>=r;i--) a[i]=b[i]; solve(nl,nr,ml,mid-1,ql,l); solve(nl,nr,mid+1,mr,r,qr); } } void print(int x) { if(x==0)puts("0"); char s[11];int i=0; while(x)s[++i]=x%10+'0',x/=10; while(i)putchar(s[i--]);puts(""); } int main() { n=sc(),m=sc(); for(int i=1;i<=n;i++) for(int j=1;j<m;j++) { int x=get(i,j),y=get(i,j+1),z=sc(); insert(x,y,z); } for(int i=1;i<n;i++) for(int j=1;j<=m;j++) { int x=get(i,j),y=get(i+1,j),z=sc(); insert(x,y,z); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int x=get(i,j); px[x]=i,py[x]=j; } memset(ans,127,sizeof(ans)); int w=0;Q=sc(); for(int i=1;i<=Q;i++) { ++w; a[w].x1=sc(),a[w].y1=sc(), a[w].x2=sc(),a[w].y2=sc(),a[w].p=i; if(a[w].x1==a[w].x2&&a[w].y1==a[w].y2)ans[i]=0,w--; } solve(1,n,1,m,1,w); for(int i=1;i<=Q;i++) //print(ans[i]); printf("%d\n",ans[i]); //cout<<endl; return 0; }
相关文章推荐
- 对分治算法的几点思考
- Hdu2066(一个人的旅行)
- Poj2638 网络流+最短路+二分答案
- Aizu1311 分层图最短路 (...大概)
- 关于“2”这个数字
- 最短路径 -- spfa
- hdu 1007 -- Quoit Design
- [Leetcode题解]004 Median of Two Sorted Arrays
- 单源最短路深度分析
- 分治法求最大连续和
- Codeforces Round #299
- poj2299 分治
- hdu5137最短路
- hdoj 1874 畅通工程 vector邻接表测试
- poj 3255 Roadblocks
- 【POJ1860】Currency Exchange
- Dijkstra求最短路与次短路
- 2014西安邀请赛部分题解
- 2014 西安邀请赛状压DP
- 2013长沙邀请赛Travel in time