//BFS广度优先搜索 //构完图后,对图中所有空的进行广搜,相当于从改点不断往外扩张,直到碰到cube或越界 //每成功广搜一个坐标就意味着有一个空洞,但最后答案要除去最外层的空洞 //因此ans - 1 #include<iostream> #include<cstring> #include<queue> using namespace std; const int MAX = 102; int t,n,x,y,z,ans; int G[MAX][MAX][MAX]; struct coord { int x,y,z; coord(int xx,int yy,int zz) { x = xx; y = yy; z = zz; } }; inline bool valid(coord co)//判断坐标是否越界 { if(co.x < 0 || co.x > 101 || co.y < 0 || co.y > 101 || co.z < 0 || co.z > 101) return false; return true; } bool bfs(coord st) { queue<coord> q; q.push(st); G[st.x][st.y][st.z] = 1; while(!q.empty()) { x = q.front().x; y = q.front().y; z = q.front().z; q.pop(); //对每个点的周围进行搜索 if(G[x+1][y][z] == 0 && valid(coord(x+1,y,z))) { G[x+1][y][z] = 1; q.push(coord(x+1,y,z)); } if(G[x-1][y][z] == 0 && valid(coord(x-1,y,z))) { G[x-1][y][z] = 1; q.push(coord(x-1,y,z)); } if(G[x][y+1][z] == 0 && valid(coord(x,y+1,z))) { G[x][y+1][z] = 1; q.push(coord(x,y+1,z)); } if(G[x][y-1][z] == 0 && valid(coord(x,y-1,z))) { G[x][y-1][z] = 1; q.push(coord(x,y-1,z)); } if(G[x][y][z-1] == 0 && valid(coord(x,y,z-1))) { G[x][y][z-1] = 1; q.push(coord(x,y,z-1)); } if(G[x][y][z+1] == 0 && valid(coord(x,y,z+1))) { G[x][y][z+1] = 1; q.push(coord(x,y,z+1)); } } return true; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&t); while(t--) { memset(G,0,sizeof(G)); scanf("%d",&n); ans = 0; while(n--) { scanf("%d%d%d",&x,&y,&z); G[x][y][z] = -1; } for(int x = 1;x <= 100;++x) for(int y = 1;y <= 100;++y) for(int z = 1;z <= 100;++z) if(!G[x][y][z] && bfs(coord(x,y,z))) ans++; printf("%d/n",ans-1); } return 0; }