列表

详情


XM39. 集合合并

描述

给定若干个32位int数字集合,每个集合中的数字无重复,譬如:
  {1,2,3}  {2,5,6}  {8}
将其中交集不为空的集合合并,保证合并完成后所有集合之间无交集,输出合并后的集合个数以及最大集合中元素的个数。

输入描述

输入格式:
1. 第一行为一个数字N,表示集合数。
2. 接下来N行,每行一个非空集合,包含若干个数字,数字之间用空格分开。
假设第i个集合的大小为Si,数据满足N<=100000,ΣSi<=500000

输出描述

输出格式:
1. 第一行为合并后的集合个数。
2. 第二个为最大集合中元素的个数。

示例1

输入:

3
1 2 3
2 5 6
8

输出:

2
5

原站题解

C++ 解法, 执行用时: 170ms, 内存消耗: 26044KB, 提交时间: 2020-08-18

//数据的输入
#include <bits/stdc++.h>
       
using namespace std;
       
constexpr int N = 100005;
       
char s[N * 100], t[15];
vector<int> a[N];
int fa[N * 10], cnt[N * 10];
unordered_map<int, int> d;
       
void splitNum(vector<int>& b, char *s) {
    int top = 0;
    for (int i = 0; s[i] != '\0'; ++i) {
        if (s[i] != ' ' && s[i] != '\n') t[top++] = s[i];
        else if (top) {
            t[top] = '\0';
            b.emplace_back(atoi(t));
            top = 0;
        }
    }
    if (top > 0) {
        t[top] = '\0';
        b.emplace_back(atoi(t));
    }
}
       
int findFa(int x) {
    if (x != fa[x]) fa[x] = findFa(fa[x]);
    return fa[x];
}
int main() {
    int n;
    scanf("%d", &n);
    int num = 0;
    getchar();
    for (int i = 0; i < n; ++i) {
        gets(s);
        splitNum(a[i], s);
        int m = a[i].size();
        for (int j = 0; j < m; ++j) {
            if (d.find(a[i][j]) == d.end()) {
                d[a[i][j]] = ++num;
            }
            a[i][j] = d[a[i][j]];
        }
    }
    for (int i = 1; i <= num; ++i) {
        fa[i] = i;
        cnt[i] = 1;
    }
    for (int i = 0; i < n; ++i) {
        int m = a[i].size();
        int u = a[i][0];
        int fu = findFa(u);
        for (int k = 1; k < m; ++k) {
            int v = a[i][k];
            int fv = findFa(v);
            if (fu != fv){
                fa[fv] = fu;
                cnt[fu] += cnt[fv];
            }
        }
    }
    int numSet = 0;
    int maxNum = 0;
    for (int i = 1; i <= num; ++i) {
        fa[i] = findFa(i);
        maxNum = max(maxNum, cnt[i]);
        if (i == fa[i]) ++numSet;
    }
    printf("%d\n%d\n", numSet, maxNum);
    return 0;
}

C++ 解法, 执行用时: 183ms, 内存消耗: 26060KB, 提交时间: 2020-07-28

#include <bits/stdc++.h>
       
using namespace std;
       
constexpr int N = 100005;
       
char s[N * 100], t[15];
vector<int> a[N];
int fa[N * 10], cnt[N * 10];
unordered_map<int, int> d;
       
void splitNum(vector<int>& b, char *s) {
    int top = 0;
    for (int i = 0; s[i] != '\0'; ++i) {
        if (s[i] != ' ' && s[i] != '\n') t[top++] = s[i];
        else if (top) {
            t[top] = '\0';
            b.emplace_back(atoi(t));
            top = 0;
        }
    }
    if (top > 0) {
        t[top] = '\0';
        b.emplace_back(atoi(t));
    }
}
       
int findFa(int x) {
    if (x != fa[x]) fa[x] = findFa(fa[x]);
    return fa[x];
}
int main() {
    int n;
    scanf("%d", &n);
    int num = 0;
    getchar();
    for (int i = 0; i < n; ++i) {
        gets(s);
        splitNum(a[i], s);
        int m = a[i].size();
        for (int j = 0; j < m; ++j) {
            if (d.find(a[i][j]) == d.end()) {
                d[a[i][j]] = ++num;
            }
            a[i][j] = d[a[i][j]];
        }
    }
    for (int i = 1; i <= num; ++i) {
        fa[i] = i;
        cnt[i] = 1;
    }
    for (int i = 0; i < n; ++i) {
        int m = a[i].size();
        int u = a[i][0];
        int fu = findFa(u);
        for (int k = 1; k < m; ++k) {
            int v = a[i][k];
            int fv = findFa(v);
            if (fu != fv){
                fa[fv] = fu;
                cnt[fu] += cnt[fv];
            }
        }
    }
    int numSet = 0;
    int maxNum = 0;
    for (int i = 1; i <= num; ++i) {
        fa[i] = findFa(i);
        maxNum = max(maxNum, cnt[i]);
        if (i == fa[i]) ++numSet;
    }
    printf("%d\n%d\n", numSet, maxNum);
    return 0;
}

上一题