对于任意两个建筑物,以它们之间的最短路为边权求出最小生成树。
则询问(x,y)的答案为最小生成树上x到y路径上边权的最大值。
BFS求出离每个点最近的建筑物以及到它的距离,可以发现只有交界处的边才有用,用这些边求MST即可。
#include<cstdio> #include<algorithm> using namespace std; const int L=2010,N=200010,K=17,inf=~0U>>1; int H,W,n,m,Q,i,j,x,y,z,p,mx; int dis[L][L][2],q[L*L][2],h=1,t; int fa[N],g[N],v[N<<1],w[N<<1],nxt[N<<1],ed,f[N][K+1],fm[N][K+1],d[N]; char s[L];bool a[L][L],vis[L][L]; struct E{int x,y;E*nxt;}*e[L*L],pool[L*L],*cur=pool; inline void up(int&a,int b){if(a<b)a=b;} inline void bfs(int x,int y,int z,int p){ if(x<1||x>H||y<1||y>W||vis[x][y]||!a[x][y])return; vis[x][y]=1,dis[x][y][0]=z,dis[x][y][1]=p,q[++t][0]=x,q[t][1]=y; } inline void check(int a,int b,int c,int d){ if(vis[a][b]&&vis[c][d]&&dis[a][b][1]!=dis[c][d][1]){ int x=dis[a][b][0]+dis[c][d][0]; E*p=cur++;p->x=dis[a][b][1];p->y=dis[c][d][1];p->nxt=e[x];e[x]=p; up(mx,x); } } int F(int x){return fa[x]==x?x:fa[x]=F(fa[x]);} inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;} void dfs(int x,int pre,int dis){ f[x][0]=pre,fm[x][0]=dis;d[x]=d[pre]+1; for(int i=1;i<=K;i++)f[x][i]=f[f[x][i-1]][i-1],fm[x][i]=max(fm[x][i-1],fm[f[x][i-1]][i-1]); for(int i=g[x];i;i=nxt[i])if(v[i]!=pre)dfs(v[i],x,w[i]); } inline int ask(int x,int y){ if(F(x)!=F(y))return -1; int t=0,i; if(d[x]<d[y])swap(x,y); for(i=K;~i;i--)if(d[f[x][i]]>=d[y])up(t,fm[x][i]),x=f[x][i]; if(x==y)return t; for(i=K;~i;i--)if(f[x][i]!=f[y][i])up(t,max(fm[x][i],fm[y][i])),x=f[x][i],y=f[y][i]; return max(t,max(fm[x][0],fm[y][0])); } inline void read(int&a){char ch;while(!(((ch=getchar())>='0')&&(ch<='9')));a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))(a*=10)+=ch-'0';} int main(){ read(H),read(W),read(n),read(Q); for(i=1;i<=H;i++)for(scanf("%s",s+1),j=1;j<=W;j++)a[i][j]=s[j]=='.'; for(i=1;i<=n;i++)read(x),read(y),bfs(x,y,0,i),fa[i]=i; while(h<=t){ x=q[h][0],y=q[h++][1],z=dis[x][y][0]+1,p=dis[x][y][1]; bfs(x-1,y,z,p),bfs(x+1,y,z,p),bfs(x,y-1,z,p),bfs(x,y+1,z,p); } for(i=1;i<=H;i++)for(j=1;j<W;j++)check(i,j,i,j+1); for(i=1;i<H;i++)for(j=1;j<=W;j++)check(i,j,i+1,j); for(i=0;i<=mx;i++)for(E*p=e[i];p;p=p->nxt)if(F(p->x)!=F(p->y))add(p->x,p->y,i),add(p->y,p->x,i),fa[fa[p->x]]=fa[p->y]; for(i=1;i<=n;i++)if(!d[i])dfs(i,0,0); while(Q--)read(x),read(y),printf("%d ",ask(x,y)); return 0; }