http://hihocoder.com/problemset/problem/1291
前几天比较忙,这次来补一下微软笔试的最后一题,这题是这次微软笔试的第四题,过的人比较少,我当时在调试B题,没时间看这一题。不过打过之前一场BestCoder的应该都会有点思路,虽然BC那题是二维,这题是三维的,但是思路应该是一样的,没错,就是离线加并查集。
正过来考虑的时候,发现第一个要求相邻块是好处理的,但是第二个要求能否到达(1000, 1000, 1000)这个条件似乎比较难判断,当时BC上的题根据题意是可以二分加搜索,但是这题的条件是不能二分的。
离线并查集的话,比较好想(如果做过BC那题的话),就是先算上所有块,搜索一遍全图,把非块的用并查集联通起来。然后倒着来拆块,看要拆的块是否和边界(这里取了(0, 0, 1)这个边界非块)的非块联通(有公共的根),然后将拆掉块的地方和周围非块的地方联通。直到某一处的块与边界不联通,那么就是No。否则最后就是Yes。
本地用dfs爆栈了,改bfs应该可以解决。不过直接交上去,评测机用dfs不会爆栈。。。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <string> #include <vector> using namespace std; const int maxN = 100005; const int maxX = 103; int ufs[105*105*105]; int n, x[maxN], y[maxN], z[maxN]; int xx[] = {-1, 1, 0, 0, 0, 0}; int yy[] = { 0, 0, -1, 1, 0, 0}; int zz[] = { 0, 0, 0, 0, -1, 1}; int findRoot(int x) { if (ufs[x] == x) return x; int fa = findRoot(ufs[x]); ufs[x] = fa; return fa; } void mergeUfs(int x, int y) { int fx, fy; fx = findRoot(x); fy = findRoot(y); ufs[fx] = fy; } bool inSameUfs(int x, int y) { int fx, fy; fx = findRoot(x); fy = findRoot(y); if (fx == fy) return true; else return false; } inline int Hash(int x, int y, int z) { return x*maxX*maxX+y*maxX+z; } void dfs(int x, int y, int z) { int t = Hash(x, y, z), tt; if (ufs[t] == -2 || ufs[t] != -1) return; if (ufs[t] == -1) ufs[t] = t; for (int i = 0; i < 6; ++i) { if (x+xx[i] < 0 || y+yy[i] < 0 || z+zz[i] <= 0) continue; if (x+xx[i] >= maxX || y+yy[i] >= maxX || z+zz[i] >= maxX) continue; tt = Hash(x+xx[i], y+yy[i], z+zz[i]); if (ufs[tt] != -1) continue; dfs(x+xx[i], y+yy[i], z+zz[i]); mergeUfs(t, tt); } } bool judge(int x, int y, int z) { bool flag = false; int t, tt, to; for (int i = 0; i < 6; ++i) { tt = Hash(x+xx[i], y+yy[i], z+zz[i]); if (ufs[tt] == -2) flag = true; } if (!flag) return false; flag = false; t = Hash(x, y, z); to = Hash(0, 0, 1); ufs[t] = t; for (int i = 0; i < 6; ++i) { tt = Hash(x+xx[i], y+yy[i], z+zz[i]); if (ufs[tt] == -2) continue; if (findRoot(to) == findRoot(tt)) flag = true; mergeUfs(t, tt); } return flag; } void input() { memset(ufs, -1, sizeof(ufs)); int t; scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d%d%d", &x[i], &y[i], &z[i]); t = Hash(x[i], y[i], z[i]); ufs[t] = -2; } for (int i = 0; i < maxX; ++i) for (int j = 0; j < maxX; ++j) { t = Hash(i, j, 0); ufs[t] = -2; } for (int k = 1; k < maxX; ++k) for (int i = 0; i < maxX; ++i) for (int j = 0; j < maxX; ++j) dfs(i, j, k); } void work() { for (int i = n-1; i >= 0; i--) { if (!judge(x[i], y[i], z[i])) { printf("No\n"); return; } } printf("Yes\n"); } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int T; scanf("%d", &T); for (int times = 1; times <= T; ++times) { input(); work(); } return 0; }
时间: 2024-10-13 20:57:23