zoukankan      html  css  js  c++  java
  • 【并查集】P3958 奶酪

    P3958 奶酪

    思路:

    因为一开始就知道可以用并查集做,只是试着写了一下。

    显然,如果两球相切/相交时是可以merge的,在全部尝试过merge之后再判断【与顶面相交的洞】和【与底面相交的洞】是否在同一集合内即可(也就是find(i)==find(j)

    卡在了两处地方:

    一是没有让所有洞两两之间都尝试一下merge(总是在担心时间复杂度……但这样完全可以过),写成了merge(i,i+1)

    二是不知道怎么判断最后得到的大集合是否能贯穿整个奶酪。其实只要先记录下能与底面相交和能与顶面相交的洞的编号,再枚举即可,也只是(O(n^2))而已,可以过的

    int fa[maxn];
    int down[maxn];
    int up[maxn];
    
    int find(int x) {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }
    
    void merge(int x, int y) {
        x = find(x);
        y = find(y);
        if (x != y) fa[x] = y;
    }
    
    struct node {
        LL x, y, z;
    }hole[maxn];
    
    LL count(node k1,node k2) {
        LL dx = (k1.x - k2.x) * (k1.x - k2.x);
        LL dy = (k1.y - k2.y) * (k1.y - k2.y);
        LL dz = (k1.z - k2.z) * (k1.z - k2.z);
        return dx + dy + dz;
    }
    
    int main()
    {
        //ios::sync_with_stdio(false);
        int t; cin >> t;while(t--){
            LL n, h, r;
            cin >> n >> h >> r;
            for (int i = 1; i <= n; i++)fa[i] = i;
            for (int i = 1; i <= n; i++) {
                cin >> hole[i].x >> hole[i].y >> hole[i].z;
            }
    
            int pos1 = 0;
            int pos2 = 0;
    
            for (int i = 1; i <= n; i++) {
                if (r >= hole[i].z) down[++pos1] = i;
                //与底面相交的洞
                if (r >= h - hole[i].z) up[++pos2] = i;
                //与顶面相交的洞
                //注意一个洞可能同时与两个面相交,不能写成else if
            }
    
            //遍历当前洞前面的所有洞,尝试连通
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= i; j++) {
                    if ((hole[i].x - hole[j].x) * (hole[i].x - hole[j].x) + (hole[i].y - hole[j].y) * (hole[i].y - hole[j].y) > r * r * 4) continue;
                    if (count(hole[i], hole[j]) <= r * r * 4) {
                        merge(i, j);
                    }
                }
            }
    
            //枚举所有与上下表面连通的洞
            int ok = 0;
            for (int i = 1; i <= pos1; i++) {
                for (int j = 1; j <= pos2; j++) {
                    if (find(down[i]) == find(up[j])) {
                        ok = 1;
                        break;
                    }
                }
                if (ok) break;
            }
            if (ok) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    # 抗战电视剧《河山》观后感 #
    SAP MM 自定义条件类型出现在采购信息记录的'条件'界面里 ?
    SAP 对HU做转库操作,系统报错
    SAP MM 采购订单与相关合同的价格差异问题分析
    2019年终总结之SAP项目实践篇
    大学教师,要做教授,请不要做叫兽!
    SAP MM 一个含有多个账号分配对象的行项目的PO及其收货
    华哥演技好!--- 电视剧《魔都风云》观后感
    SAP 如何看某个TR是否传入了Q或者P系统?
    Linux IO 模型
  • 原文地址:https://www.cnblogs.com/streamazure/p/13458811.html
Copyright © 2011-2022 走看看