zoukankan      html  css  js  c++  java
  • AcWing 1608. 森林里的鸟 并查集

    地址 https://www.acwing.com/solution/content/15062/

    一些科学家为森林中成千上万的鸟类拍照。
    
    假设所有出现在同一张照片中的鸟都属于同一棵树。
    
    请你帮助科学家计算森林中树木的最大数量,对于任何一对鸟类,请判断它们是否在同一棵树上。
    
    输入格式
    第一行包含整数 N 表示照片数量。
    
    接下来 N 行,每行描述一张照片,格式如下:
    
    K B1 B2 … BK
    K 表示照片中的鸟的数量,Bi 是鸟的具体编号。
    
    保证所有照片中的鸟被连续编号为 1 到某个不超过 104 的整数。
    
    再一行包含整数 Q。
    
    接下来 Q 行,每行包含两个鸟的编号,表示一组询问。
    
    输出格式
    第一行输出最大可能的树的数量以及鸟的数量。
    
    接下来对于每个询问,如果被询问的两个鸟在同一棵树上,则在一行中输出 Yes,否则输出 No。
    
    数据范围
    1≤N≤104,
    1≤K≤10,
    1≤Q≤104
    输入样例:
    4
    3 10 1 2
    2 3 4
    4 1 5 7 8
    3 9 6 4
    2
    10 5
    3 7
    输出样例:
    2 10
    Yes
    No

    算法1
    并查集裸题
    考察对并查集原理和操作。

    询问完所有数据后,在一棵树上的鸟的编号可以使用并查集合并。
    鸟的编号是1~n,那么输入的最大编号就是鸟的数目
    树的数目其实就是1~n中并查集的种类
    根据并查集的定义,f[1]~f[n]中 f[i]!=i 就说明他和别人在同一个并查集里
    那么我们只要统计 f[i]==i的个数 就是并查集的集合数目也就是题目中树的数目

    C++ 代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    
    const int N = 10010;
    
    int f[N];
    int cnt[N];
    
    void init() {
        for (int i = 1; i < N; i++) {
            f[i] = i;
            cnt[i] = 1;
        }
    }
    
    int find(int x) {
        return f[x] == x ? x : f[x] = find(f[x]);
    }
    
    int n, m;
    
    vector<int> v[N];
    int uni[N];
    int maxNum = -1;
    
    int main()
    {
        cin >> n;
        init();
        for (int i = 0; i < n; i++) {
            int num = 0;
            cin >> num;
            for (int j = 0; j < num; j++) {
                int t;cin >> t;
                maxNum = max(t, maxNum);
                v[i].push_back(t);
            }
            for (int j = 0; j < v[i].size() - 1; j++) {
                int a = v[i][j]; int b = v[i][j + 1];
                a = find(a); b = find(b);
                if (a != b) {
                    f[a] = b;
                    cnt[b] += cnt[a];
                }
            }
        }
    
        int ans = 0;
        for (int i = 1; i <= maxNum; i++) {
            int idx = find(i);
            uni[idx]++;
        }
    
        for (int i = 1; i <= maxNum; i++) {
            if (uni[i] != 0) ans++;
        }
        cout << ans << " "<< maxNum << endl;
    
        cin >> m;
    
        for (int i = 0; i < m; i++)
        {
            int a, b;
            cin >> a >> b;
    
            if (find(a) == find(b)) {
                cout << "Yes" << endl;
            }
            else {
                cout << "No" << endl;
            }
        }
    
        return 0;
    }
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/itdef/p/13169327.html
Copyright © 2011-2022 走看看