计蒜客 奶酪 (并查集)

Posted UNBROKEN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 奶酪 (并查集)相关的知识,希望对你有一定的参考价值。


链接 : Here!

思路 :

  • 其实这个是一道简单的并查集问题, 判断$Jerry$是否能从下表面跑到上表面, 其实质上是判断上表面和下表面是否连通, 因此这道问题就变成了判断连通性的问题了. 判断标准是如果$d <= 2 * r$ ($d$为两球心之间的距离), 那么就合并两个集合即可

思考 : 将知识穿成线索,做等价迁移,将复杂问题变成简单问题.

代码 :

/*************************************************************************
    > File Name: t13.cpp
    > Author: 
    > Mail: 
    > Created Time: 2017年11月21日 星期二 16时33分31秒
 ************************************************************************/

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;

#define MAX_N 1010
typedef long long ll;
int par[MAX_N];
int size[MAX_N];
ll n, h, r;

struct Point {
    ll x, y, z;
};

double check(Point a, Point b) {
    return (sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z)) <= 2 * r);
}

void init() {
    for (int i = 0 ; i < MAX_N ; ++i) {
        par[i] = i;
        size[i] = 1;
    }
}
int find(int x) {
    return x == par[x] ? x : (par[x] = find(par[x]));
}
void merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (size[x] > size[y]) {
        size[x] += size[y];
        par[y] = x;
    } else {
        size[y] += size[x];
        par[x] = y;
    }
}
int same(int x, int y) {
    return find(x) == find(y);
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        init();
        Point data[MAX_N];
        scanf("%lld%lld%lld", &n, &h, &r);
        for (int i = 2 ; i <= n + 1 ; ++i) {
            scanf("%lld%lld%lld", &data[i].x, &data[i].y, &data[i].z);
        }
        // 先把能接触到地面的点加入到地面集合0中
        for (int i = 2 ; i <= n + 1 ; ++i) {
            if (fabs(0 - data[i].z) > r) continue;
            if (same(0, i)) continue;    
            merge(0, i);
        }
        // 再把能接触到上端的点加入到顶端集合1中
        for (int i = 2 ; i <= n + 1 ; ++i) {
            if (fabs(h - data[i].z) > r) continue;
            if (same(1, i)) continue;
            merge(1, i);
        }
        
        for (int i = 2 ; i <= n + 1 ; ++i) {
            for (int j = 2 ; j <= n + 1 ; ++j) {
                if (same(i, j)) continue;
                if (!check(data[i], data[j])) continue;
                merge(i, j);
            }
        }

        if (same(0, 1)) {
            printf("Yes\n");
        } else {
            printf("No\n");
        }
    }
    return 0;
}

以上是关于计蒜客 奶酪 (并查集)的主要内容,如果未能解决你的问题,请参考以下文章

计蒜客课程竞赛入门--冗余关系(并查集) 流程记

计蒜客2018复赛 贝壳找房魔法师顾问

贝壳找房魔法师顾问[并查集+DAG判断]

10.27T4 奶酪 并查集

2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

NOIP 2017 Day2 T1 奶酪