题目描述:
题解:
暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受。
考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的。
所以说转移有两种,一种是$A$推$B$一下,另一种是$A$绕到$B$另一侧。
第一种转移显然$O(1)$,瓶颈在第二种。
发现这对点满足点双,所以建出广义圆方树,判两个点是否同父亲或一个点是另一个点的爷爷。
时间复杂度$O(n^2)$。
代码:
扫描二维码关注公众号,回复:
6164872 查看本文章
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1550; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } int n,m,Q,nam[N][N],tot,rtx,rty,rt,stx,sty,st,hed[N*N],cnt=1; char mp[N][N]; bool check(int x,int y){return x&&y&&x<=n&&y<=m;} int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1}; struct EG { int to,nxt; }e[4*N*N]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int dfn[N*N],low[N*N],tim,fa[N*N*2]; int sta[N*N*2],tl; void tarjan(int u,int f) { dfn[u] = low[u] = ++tim; sta[++tl] = u; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==f)continue; if(!dfn[to]) { tarjan(to,u); low[u] = min(low[u],low[to]); if(low[to]>=dfn[u]) { int now = ++tot; fa[now] = u; int c = -1; while(c!=to) { c = sta[tl--]; fa[c] = now; } } }else low[u] = min(low[u],dfn[to]); } } bool ck(int u,int v) { if(fa[u]==fa[v])return 1; if(fa[fa[v]]==u)return 1; if(fa[fa[u]]==v)return 1; return 0; } bool dp[N][N][4]; bool vis[N][N]; struct Pair { int x,y; Pair(){} Pair(int x,int y):x(x),y(y){} }; void bfs() { queue<Pair>q; q.push(Pair(rtx,rty)); vis[rtx][rty] = 1; while(!q.empty()) { Pair tp = q.front();q.pop(); int x = tp.x,y = tp.y; for(int k=0;k<4;k++) { int xx = x+dx[k],yy = y+dy[k]; if(!nam[xx][yy])continue; if(xx==stx&&yy==sty)dp[stx][sty][k]=1; else if(!vis[xx][yy])vis[xx][yy]=1,q.push(Pair(xx,yy)); } } } struct Tri { int x,y,z; Tri(){} Tri(int x,int y,int z):x(x),y(y),z(z){} }; void sol() { queue<Tri>q; for(int k=0;k<4;k++)if(dp[stx][sty][k]) q.push(Tri(stx,sty,k)); while(!q.empty()) { Tri tp = q.front(); q.pop(); int x = tp.x,y = tp.y,k = tp.z; if(nam[x+dx[k]][y+dy[k]]&&!dp[x+dx[k]][y+dy[k]][k])dp[x+dx[k]][y+dy[k]][k]=1,q.push(Tri(x+dx[k],y+dy[k],k)); for(int i=0;i<4;i++)if(nam[x-dx[i]][y-dy[i]]&&i!=k&&ck(nam[x-dx[k]][y-dy[k]],nam[x-dx[i]][y-dy[i]])&&!dp[x][y][i]) dp[x][y][i]=1,q.push(Tri(x,y,i)); } } bool cck(int x,int y){return dp[x][y][0]||dp[x][y][1]||dp[x][y][2]||dp[x][y][3]||(x==stx&&y==sty);} int main() { // freopen("tt.in","r",stdin); read(n),read(m),read(Q); for(int i=1;i<=n;i++) { scanf("%s",mp[i]+1); for(int j=1;j<=m;j++)if(mp[i][j]!='#') { nam[i][j] = ++tot; if(mp[i][j]=='A')rt=tot,rtx=i,rty=j; if(mp[i][j]=='B')st=tot,stx=i,sty=j; } } for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(mp[i][j]!='#') { int u = nam[i][j]; for(int x,y,k=0;k<4;k++) { x = i+dx[k],y = j+dy[k]; if(!check(x,y)||mp[x][y]=='#')continue; ae(u,nam[x][y]); } } tarjan(rt,0); bfs();sol(); for(int x,y,i=1;i<=Q;i++) { read(x),read(y); puts(cck(x,y)?"YES":"NO"); } return 0; }