题意
给定一个 $n \times n$ 的点阵, 形成一个网格图.
最初的时候四连通.
$m$ 次操作, 每次删去一条边 $(u, v)$ , 问 $u$ 和 $v$ 是否仍然连通.
$2 \le n \le 1500, 1 \le m \le 2n(n - 1)$ .
分析
将平面图转化为它的对偶图.
每次相当于将两个平面区域合并.
对于删去一条边, 若与它相邻的两个区域连通, 那么操作后两个点中有一个点被区域包围, 一个点被隔在了外面, 所以不连通, 反之仍然连通.
实现
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 inline int rd(void) { 7 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 8 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 9 } 10 inline char rdc(void) { char c = getchar(); while (!isalpha(c)) c = getchar(); return c; } 11 12 const int N = 2500000; 13 14 int n, m, f[N]; 15 inline int id(int x, int y) { 16 bool Legal = (1 <= x && x < n && 1 <= y && y < n); 17 return Legal ? (x-1)*(n-1)+y : 0; 18 } 19 inline int Find(int x) { return f[x] == x ? x : f[x] = Find(f[x]); } 20 inline bool Union(int x, int y) { 21 int fx = Find(x); 22 int fy = Find(y); 23 bool ret = (fx != fy); 24 return f[fx] = fy, ret; 25 } 26 27 int main(void) { 28 #ifndef ONLINE_JUDGE 29 freopen("bzoj4423.in", "r", stdin); 30 #endif 31 32 n = rd(), m = rd(); 33 F(i, 0, (n-1)*(n-1)) f[i] = i; 34 35 bool Last = true; 36 F(i, 1, m) { 37 int a = rd(), b = rd(); char c = rdc(); 38 int _a = rd(), _b = rd(); char _c = rdc(); 39 if (!Last) a = _a, b = _b, c = _c; 40 if (c == ‘N‘) 41 Last = Union(id(a, b), id(a-1, b)); 42 else Last = Union(id(a, b), id(a, b-1)); 43 puts(Last ? "TAK" : "NIE"); 44 } 45 46 return 0; 47 }
时间: 2024-10-25 14:34:53