洛谷P3958 奶酪 题解 并查集

题目链接:https://www.luogu.com.cn/problem/P3958

解题思路:
并查集。
如果两个奶酪的距离 \(\le 2 \cdot r\) ,则合并。
再开两个点:\(n+1\) 表示底,\(n+2\) 表示顶。
然后如果一个点的 \(z_i \le r\),则将该点与 \(n+1\) 合并;
如果一个点的 \(z_i \ge h-r\),则将改点与 \(n+2\) 合并。
最后判断 \(n+1\)\(n+2\) 是否属于同一个集合即可。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10010, maxm = maxn*2;
int n, T, f[maxn];
double h, r, x[maxn], y[maxn], z[maxn];
void init() {
    for (int i = 1; i <= n+2; i ++) f[i] = i;
}
int Find(int x) {
    return x == f[x] ? x : f[x] = Find(f[x]);
}
void Union(int x, int y) {
    int a = Find(x), b = Find(y);
    f[a] = f[b] = f[x] = f[y] = min(a, b);
}
int main() {
    cin >> T;
    while (T --) {
        cin >> n >> h >> r;
        init();
        for (int i = 1; i <= n; i ++)
            cin >> x[i] >> y[i] >> z[i];
        for (int i = 1; i <= n; i ++) {
            for (int j = i+1; j <= n; j ++) {
                if (sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j])) <= 2*r) {
                    Union(i, j);
                }
            }
        }
        for (int i = 1; i <= n; i ++) {
            if (z[i] <= r) Union(i, n+1);
            if (z[i] >= h-r) Union(i, n+2);
        }
        puts(Find(n+1) == Find(n+2) ? "Yes" : "No");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/quanjun/p/12340880.html
今日推荐