NC53257. 水壶
描述
输入描述
第一行四个空格分隔的整数H,W,P,Q。
接下来H行,第i行有一个长度为W的字符串,每个字符都是.或#之一,.表示这个位置是建筑物或原野,#表示这个位置是墙壁。
接下来P行描述IOI市每个建筑物的位置,第i行有两个空格分隔的整数和,表示第i个建筑物的位置在第行第列。保证这个位置在地图中是.。
接下来Q行,第i行有两个空格分隔的整数。
输出描述
输出Q行,第i行一个整数,表示要从建筑物移动到,至少需要多大的水壶。
如果无法到达,输出-1。如果不需要经过原野就能到达,输出0。
示例1
输入:
5 5 4 4 ..... ..##. .#... ..#.. ..... 1 1 4 2 3 3 2 5 1 2 2 4 1 3 3 4
输出:
3 4 4 2
说明:
示例2
输入:
5 5 3 2 ...#. ..#.. #.... .##.. ...#. 1 3 5 2 1 5 1 2 1 3
输出:
-1 7
C++(clang++11) 解法, 执行用时: 978ms, 内存消耗: 114012K, 提交时间: 2021-02-13 08:43:26
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int dx[4]={0,-1,0,1}; const int dy[4]={-1,0,1,0}; struct ac { int x,y,c,next; }e[410000];int tlen,last[210000]; void insx(int x,int y,int c){tlen++;e[tlen].x=x;e[tlen].y=y;e[tlen].c=c;e[tlen].next=last[x];last[x]=tlen;} struct point{int x,y;}; queue<point> q; struct edge { int x,y,c; }a[16160400];int len; void ins(int x,int y,int c) { len++; a[len].x=x;a[len].y=y;a[len].c=c; } int v[2100][2100],d[2100][2100]; bool cmp(edge n1,edge n2){return n1.c<n2.c;} int h,w,p,Q; bool vis[2100][2100]; char s[2100][2100]; int fa[210000]; int findfa(int x) { if(fa[x]!=x)fa[x]=findfa(fa[x]); return fa[x]; } int f[210000][22],dep[810000]; int maxn[210000][22]; void pre_tree_node(int x) { for(int i=1;i<=18;i++)f[x][i]=f[f[x][i-1]][i-1],maxn[x][i]=max(maxn[x][i-1],maxn[f[x][i-1]][i-1]); for(int k=last[x];k;k=e[k].next) { int y=e[k].y; if(y!=f[x][0]) { f[y][0]=x;maxn[y][0]=e[k].c; dep[y]=dep[x]+1; // printf("%d %d %d\n",e[k].x,e[k].y,e[k].c); pre_tree_node(y); } } } int getsum(int x,int y) { int ret=0; if(dep[x]<dep[y])swap(x,y); for(int i=17;i>=0;i--) if(dep[f[x][i]]>=dep[y])ret=max(ret,maxn[x][i]),x=f[x][i]; if(x==y)return ret; for(int i=17;i>=0;i--) if(f[x][i]!=f[y][i])ret=max(ret,max(maxn[x][i],maxn[y][i])),x=f[x][i],y=f[y][i]; return max(ret,max(maxn[x][0],maxn[y][0])); } int main() { h=read();w=read();p=read();Q=read(); for(int i=1;i<=h;i++)scanf("%s",s[i]+1); memset(vis,true,sizeof(vis)); memset(v,0,sizeof(v)); for(int i=1;i<=p;i++) { point u; u.x=read();u.y=read(); vis[u.x][u.y]=false;v[u.x][u.y]=i;d[u.x][u.y]=0; q.push(u); } while(!q.empty()) { point u=q.front();q.pop(); for(int i=0;i<=3;i++) { point pp; pp.x=u.x+dx[i];pp.y=u.y+dy[i]; if(pp.x>=1 && pp.x<=h && pp.y>=1 && pp.y<=w) { if(vis[pp.x][pp.y]==true && s[pp.x][pp.y]!='#') { v[pp.x][pp.y]=v[u.x][u.y]; d[pp.x][pp.y]=d[u.x][u.y]+1; vis[pp.x][pp.y]=false; q.push(pp); } else if(vis[pp.x][pp.y]==false && s[pp.x][pp.y]!='#' && v[pp.x][pp.y]!=v[u.x][u.y]) { ins(v[pp.x][pp.y],v[u.x][u.y],d[pp.x][pp.y]+d[u.x][u.y]); } } } } sort(a+1,a+1+len,cmp); for(int i=1;i<=p;i++)fa[i]=i; int cnt=p;tlen=0;memset(last,0,sizeof(last)); for(int i=1;i<=len;i++) { int u=findfa(a[i].x),v=findfa(a[i].y); if(u!=v) { fa[u]=v; insx(a[i].x,a[i].y,a[i].c); insx(a[i].y,a[i].x,a[i].c); cnt--; if(cnt==1)break; } } // for(int i=1;i<=tlen;i+=2)printf("%d %d %d\n",e[i].x,e[i].y,e[i].c); for(int i=1;i<=p;i++) if(fa[i]==i) { dep[i]=1;pre_tree_node(i); } /* else { for(int i=1;i<=p;i++) if(fa[i]==i) { f[i]=0;dep[i]=0;dep_s[1]=0; pre_tree_node(i); } }*/ while(Q--) { int x=read(),y=read(); int u=findfa(x),v=findfa(y); if(u!=v){printf("-1\n");continue;} printf("%d\n",getsum(x,y)); } return 0; }