这个问题是不好判断的
考虑简单点的,\((1,1)\) 到 \((h,w)\) 是否连通
那么只要在最外围一圈 #
(显然一些位置不能加),判断 \((h+1,n)\) 和 \((0,w+1)\) 是否能通过 #
八连通即可
如果是双连通呢?只要这两点所在连通块不能通过只加一个 #
就连通
看起来很不可做的题猜测一些简单结论就很可做了
判断否就考虑加一个 #
就连通的位置,这个 #
必然是连接了两个连通块
考虑这两个连通块的类别,一是新填的两个 #
,O(k^2) 枚举即可
二是连接了原图中的两个连通块,这两个连通块又通过新的 #
连通了 \((h+1,n)\) 或 \((0,w+1)\)
于是把所有这样的连通块记录下来,判断两两是否在原图中只加一个 #
就连通
三是一个新 #
和原图中的连通块,发现处理可以和二一样
判断两连通块是否只加一个 #
就连通可以用哈希表预处理
一次询问是临时的,可撤销并查集即可
#include <bits/stdc++.h>
#define IN inline
#define eb emplace_back
using namespace std;
int n, m, q, id[1005][1005];
char str[1005], mp[1005][1005];
const int N = 1e6 + 5e3;
struct DSU {
int fa[N], sz[N], top;
struct Edge{int u, v;}stk[N];
IN int find(int x){while (fa[x] != x) x = fa[x]; return x;}
IN void merge(int x, int y) {
int u = find(x), v = find(y);
if (u == v) return; if (sz[u] > sz[v]) swap(u, v);
fa[u] = v, sz[v] += sz[u], stk[++top] = Edge{u, v};
}
IN void clear(int lst) {
for(int u, v; top != lst; --top)
u = stk[top].u, v = stk[top].v, sz[v] -= sz[u], fa[u] = u;
}
}T1, T2;
int fx[9][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}};
unordered_map<int, int> hs[N];
void dfs(int x, int y, int d, int p) {
if ((x == 2 && y == 2) || (x == n - 1 && y == m - 1)) return;
if (mp[x][y] == '#') hs[p][T1.find(id[x][y])] = 1;
if (!d) return;
for(int k = 0; k < 8; k++) {
int xx = x + fx[k][0], yy = y + fx[k][1];
if (id[xx][yy]) dfs(xx, yy, d - 1, p);
}
}
void Init() {
scanf("%d%d%d", &n, &m, &q), n += 2, m += 2;
for(int i = 2; i < n; i++) scanf("%s", mp[i] + 2);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) id[i][j] = (i - 1) * m + j;
for(int j = 1; j <= m; j++) mp[1][j] = mp[n][j] = '#';
for(int i = 1; i <= n; i++) mp[i][1] = mp[i][m] = '#';
mp[1][1] = mp[1][2] = mp[2][1] = mp[n - 1][m] = mp[n][m - 1] = mp[n][m] = '.';
for(int i = 1; i <= n * m; i++) T1.fa[i] = i, T1.sz[i] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) if (mp[i][j] == '#')
for(int k = 0; k < 8; k++) {
int x = i + fx[k][0], y = j + fx[k][1];
if (id[x][y] && mp[x][y] == '#') T1.merge(id[i][j], id[x][y]);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) dfs(i, j, 2, T1.find(id[i][j]));
for(int i = 1; i <= n * m; i++) T2.fa[i] = T1.fa[i], T2.sz[i] = T1.sz[i];
}
int X[15], Y[15];
int main() {
Init();
for(; q; --q) {
int K; scanf("%d", &K);
for(int i = 1; i <= K; i++) scanf("%d%d", &X[i], &Y[i]), mp[++X[i]][++Y[i]] = '#';
int lst = T2.top;
for(int i = 1; i <= K; i++)
for(int k = 0; k < 8; k++) {
int x = X[i] + fx[k][0], y = Y[i] + fx[k][1];
if (id[x][y] && mp[x][y] == '#') T2.merge(id[X[i]][Y[i]], id[x][y]);
}
int flag = 0;
for(int i = 1; i <= K && !flag; i++)
for(int j = 1; j <= K; j++) if (max(abs(X[i] - X[j]), abs(Y[i] - Y[j])) <= 2) {
if (T2.find(id[X[i]][Y[i]]) == T2.find(id[1][m]) && T2.find(id[X[j]][Y[j]]) == T2.find(id[n][1])) {
flag = 1; break;
}
}
vector<int> Vr, Vl; Vr.eb(T1.find(id[1][m])), Vl.eb(T1.find(id[n][1]));
for(int i = 1; i <= K; i++) {
for(int k = 0; k <= 8; k++) {
int x = X[i] + fx[k][0], y = Y[i] + fx[k][1];
if (id[x][y] && T2.find(id[x][y]) == T2.find(id[1][m])) Vr.eb(T1.find(id[x][y]));
if (id[x][y] && T2.find(id[x][y]) == T2.find(id[n][1])) Vl.eb(T1.find(id[x][y]));
}
}
for(auto kr : Vr) for(auto kl : Vl)
if (hs[kr].find(kl) != hs[kr].end() || hs[kl].find(kr) != hs[kl].end()){flag = 1; break;}
if (!flag) puts("YES"); else puts("NO"); fflush(stdout);
T2.clear(lst); for(int i = 1; i <= K; i++) mp[X[i]][Y[i]] = '.';
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章