• 天梯赛L2 024


    在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
    输入格式
    输入在第一行给出一个正整数N(≤10^4​​ ),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:
    K P[1] P[2] ⋯ P[K]
    其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过10^4
    ​之后一行给出一个非负整数Q(≤10^​4​​ ),是查询次数。随后Q行,每行给出一对被查询的人的编号。
    输出格式
    首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y,否则输出N。
    输入样例
    4
    3 10 1 2
    2 3 4
    4 1 5 7 8
    3 9 6 4
    2
    10 5
    3 7
    输出样例
    10 2
    Y
    N

    在不同小圈子的人也有可能在同一个部落, 注意处理

    并查集
    参考资料:
    并查集——简单易懂(内附并查集删除操作)
    并查集的使用及其实现
    数据结构–并查集的原理及实现

    AC代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #define mst(a) memset(a,0,sizeof(a));
    using namespace std;
    
    const int maxn = 10000 + 10;
    int f[maxn];
    
    void init(){ //初始化
        for( int i = 1; i < maxn; i++ )
            f[i] = i;
        return;
    }
    
    int _find( int a ){ //递归查询根节点
        if( a != f[a] )
            f[a] = _find(f[a]);
        return f[a];
    }
    
    void _union( int a, int b ){ //合集
        int aa = _find(a);
        int bb = _find(b);
        if( aa != bb )  f[bb] = aa;
        return;
    }
    
    int main()
    {
        mst(f);
        init();
        int T, n, a, b;
        scanf("%d",&T);
        int tre = 0;
        int m = -1;
        while(T--){
            scanf("%d",&n);
            if( n == 1 ){
                scanf("%d",&a);
                m = max(m, a); //每次更新最大编号
            }
            else{
                int root;
                for( int i = 0; i < n; i++ ){
                    scanf("%d",&a);
                    m = max(m, a);
                    if( i == 0 )   root = a;
                    else _union(root, a);
                }
            }
        }
        for( int i = 1; i <= m; i++ )
            if( f[i] == i )
                tre++;
        printf("%d %d
    ", m, tre);
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&a,&b);
            if( _find(a) == _find(b) )  printf("Y
    ");
            else printf("N
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    #Linux 系统管理命令 | top命令
    Linux 操作文件目录
    背包问题(1)背包的引入
    硬币找零问题
    输入一个正数 n,输出所有和为 n 连续正数序列。 java实现
    张小二求职记之 单例模式(三)之决战多线程
    张小二求职 之单例模式(一)
    张小二求职记之 单例模式(二)
    待修改 nyoj 412 又是一个遗留问题
    nyoj 904 hashmap
  • 原文地址:https://www.cnblogs.com/JinxiSui/p/9740585.html
Copyright © 2020-2023  润新知