題目
描述
現有一塊大奶酪,它的高度爲 ,它的長度和寬度我們可以認爲是無限大的,奶酪中間有許多半徑相同的球形空洞。我們可以在這塊奶酪中建立空間座標系,在座標系中,奶酪的下表面爲 ,奶酪的上表面爲 。
現在,奶酪的下表面有一隻小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐 標。如果兩個空洞相切或是相交,則 Jerry 可以從其中一個空洞跑到另一個空洞,特別地,如果一個空洞與下表面相切或是相交,Jerry 則可以從奶酪下表面跑進空洞;如果一個空洞與上表面相切或是相交,Jerry 則可以從空洞跑到奶酪上表面。
位於奶酪下表面的 Jerry 想知道,在不破壞奶酪的情況下,能否利用已有的空洞跑到奶酪的上表面去?
空間內兩點 、 的距離公式如下:
輸入
每個輸入文件包含多組數據。
輸入文件的第一行,包含一個正整數 ,代表該輸入文件中所含的數據組數。
接下來是 組數據,每組數據的格式如下: 第一行包含三個正整數 和 ,兩個數之間以一個空格分開,分別代表奶酪中空洞的數量,奶酪的高度和空洞的半徑。
接下來的 行,每行包含三個整數 ,兩個數之間以一個空格分開,表示空洞球心座標爲 。
輸出
輸出文件包含 行,分別對應 組數據的答案,如果在第 組數據中,Jerry 能從下表面跑到上表面,則輸出 “Yes”,如果不能,則輸出 “No” (均不包含引號)。
樣例輸入
3
2 4 1
0 0 1
0 0 3
2 5 1
0 0 1
0 0 4
2 5 2
0 0 2
2 0 4
樣例輸出
Yes
No
Yes
數據規模與約定
對於 20%的數據, , ,座標的絕對值不超過 10,000。
對於 40%的數據, , ,座標的絕對值不超過 10,000。
對於80%的數據, , ,座標的絕對值不超過10,000。
對於 100%的數據, , , ,座標的絕對值不超過 1,000,000,000。
解題思路
設下底面爲點 ,上底面爲點 ,枚舉兩個點看它們是否連通,連通即將它們用並查集並起來,最後看 與 是否連通即可。
Code
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
typedef long double LB;
const int N = 1005;
int CASES, n, h, S, T;
LL r;
struct Node{
int x, y, z;
}node[N];
inline LB dist(int a, int b){
return sqrt((LB)(node[a].x-node[b].x)*(node[a].x-node[b].x)+(LB)(node[a].y-node[b].y)*(node[a].y-node[b].y)+(LB)(node[a].z-node[b].z)*(node[a].z-node[b].z));
}
int fa[N];
void init(){
for(int i = 1; i <= n+2; i++) fa[i] = i;
}
int findfa(int x){
if(fa[x] != x) fa[x] = findfa(fa[x]);
return fa[x];
}
void unionn(int x, int y){
fa[findfa(y)] = findfa(x);
}
int main(){
scanf("%d", &CASES);
while(CASES--){
scanf("%d%d%lld", &n, &h, &r);
init();
S = n + 1, T = n + 2;
for(int i = 1; i <= n; i++){
scanf("%d%d%d", &node[i].x, &node[i].y, &node[i].z);
for(int j = 1; j < i; j++){
if(dist(i, j) <= 2 * r && findfa(i) != findfa(j))
unionn(i, j);
}
if(node[i].z + r >= h) unionn(i, T);
if(node[i].z - r <= 0) unionn(i, S);
}
if(findfa(T) == findfa(S)) puts("Yes");
else puts("No");
}
return 0;
}