P3958 [NOIP2017 提高组] 奶酪 - 洛谷题解

发布时间 2023-09-21 16:02:18作者: DreamOfSJ

题目链接 :[P3958] NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

这道题可以用并查集求解,我参考了一些大佬的题解,判断底层和顶层是否连通的条件可以为  find(0) == find(n + 1)

其中0为底层,n+1为顶层。

#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
struct p{
    int x, y, z;
}point[1005];
double dist(p p1, p p2) {
    return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2) + pow(p1.z - p2.z, 2));
}
int f[1005];    // 底层为0,顶层为n+1 
int find(int x) {
    return x == f[x] ? x : f[x] = find(f[x]);
} // 路径压缩 
void merge(int a, int b) {
    int faA = find(a);
    int faB = find(b);
    if(faA != faB)
        f[faA] = faB;
} // 合并 
int t;
int n, h, r;
int main() {
    scanf("%d", &t);
    vector<bool> res;
    while(t--){
        scanf("%d %d %d", &n, &h, &r);
        // 初始化并查集
        for(int i = 0; i <= n + 1; i++) {
            f[i] = i;
        } 
         for(int i = 1; i <= n; i++) {
            int x, y, z;scanf("%d %d %d", &x, &y, &z);
            point[i] = (p){x, y, z};
            if(z - r <= 0) merge(i, 0); // 合并到底层 
            if(z + r >= h) merge(i, n + 1); // 合并到顶层 
            // 洞间合并
            for(int j = 1; j < i; j++) {
                if(dist(point[i], point[j]) <= 2 * r) {
                    merge(j, i);
                }
            } 
         }  
         if(find(0) == find(n + 1)) printf("Yes\n");
         else printf("No\n");
    }
    return 0;
}