• 吃瓜题2(虚拟分类并查集+启发式合并)


    题意:
    与吃瓜题1题意一致,只是西瓜的种类从两种变成了无数种。

    题解:
    在吃瓜题1里,由于只有两类西瓜,因此我们可以使用分类的方法来表示异同。而在这题中,由于种类数无穷,我们只有记录每个节点的对立节点,在询问x与y的关系时,我们查询x的对立节点集合中是否出现y节点。
    那么如何记录对立节点集呢?我们采用set

    当两个节点确定异种的时候,我们分别在set[x]和set[y]中添加y和x
    当两个节点确定同种的时候,我们将他们的set合并到一起。合并是要注重技巧的!每次,我们选择较小的set,添加到较大的set中。因此,最坏情况其实就类似于一个二叉树的合并次数,大约为N次。

    #include<cstdio>
    #include<set>
    using namespace std;
    
    const int maxn = 1e6 + 5;
    int pre[maxn];
    set<int>diff[maxn];
    
    int findset(int x) {
        if (x == pre[x]) return x;
        else return pre[x] = findset(pre[x]);
    }
    
    void unionset(int x,int y) {
        int fx = findset(x);
        int fy = findset(y);
        if (diff[fx].size() < diff[fy].size()) {
            //swap(fx, fy);
            pre[fx] = fy;
            for (set<int>::iterator it = diff[fx].begin(); it != diff[fx].end(); it++) {
                int tmp = *it;
                tmp = findset(tmp);
                diff[fy].insert(tmp);
                diff[tmp].insert(fy);
            }
        }
        else {
            //swap(fx, fy);
            pre[fy] = fx;
            for (set<int>::iterator it = diff[fy].begin(); it != diff[fy].end(); it++) {
                int tmp = *it;
                tmp = findset(tmp);
                diff[fx].insert(tmp);
                diff[tmp].insert(fx);
            }
        }
    }
    
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++) {
            pre[i] = i;
        }
        while(m--) {
            char s[3];
            int x, y, id;
            scanf("%s", s);
            if (s[0] == 'A') {
                scanf("%d%d%d", &x, &y, &id);
                if (id == 1) {
                    unionset(x, y);
                }
                else {
                    int fx = findset(x);
                    int fy = findset(y);
                    diff[fx].insert(fy);
                    diff[fy].insert(fx);
                }
            }
            else {
                scanf("%d%d", &x, &y);
                int fx = findset(x);
                int fy = findset(y);
                if (fx==fy) printf("1
    ");
                else if (diff[fx].find(fy) != diff[fx].end()) 
                    printf("2
    ");
                else printf("3
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    老毛桃PE修改方法(屏蔽更改主页,屏蔽加装的绿色浏览器)
    老毛桃winpe优盘启动系统个性修改全攻略
    SQL2000和SQL2005和SQL2008同时安装问题
    基于FFmpeg的音频编码(PCM数据编码成AAC android)
    springboot + mybatis +easyUI整合案例
    spring thymeleaf 自定义标签
    速度挑战
    兼顾pc和移动端的textarea字数监控的实现方法
    CSS3+JS 实现的便签应用
    JavaScript实现碰撞检测(分离轴定理)
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489844.html
Copyright © 2020-2023  润新知