Codeforces Round 899 (Div. 2) B. Sets and Union (模拟,数学)

你有 n n n 个整数集合 S 1 , S 2 , ... , S n S_{1}, S_{2}, \ldots, S_{n} S1,S2,...,Sn 。如果可以从 S 1 , S 2 , ... , S n S_{1}, S_{2}, \ldots, S_{n} S1,S2,...,Sn 中选择一些(也可能一个都不选),从而使 S S S 等于它们的合集 † ^{\dagger} † ,那么我们就把这个集合 S S S 称为可达到的集合。如果在 S 1 , S 2 , ... , S n S_{1}, S_{2}, \ldots, S_{n} S1,S2,...,Sn 中一个也不选,那么它们的联合就是空集。

求一个可达到的 S S S 中元素的最大数目,使得 S ≠ S 1 ∪ S 2 ∪ ... ∪ S n S \neq S_{1} \cup S_{2} \cup \ldots \cup S_{n} S=S1∪S2∪...∪Sn .

† ^{\dagger} † 集合 A 1 , A 2 , ... , A k A_1, A_2, \ldots, A_k A1,A2,...,Ak 的联集定义为至少存在于其中一个集合中的元素的集合。用 A 1 ∪ A 2 ∪ ... ∪ A k A_1 \cup A_2 \cup \ldots \cup A_k A1∪A2∪...∪Ak 表示。例如, 2 , 4 , 6 ∪ 2 , 3 ∪ 3 , 6 , 7 = 2 , 3 , 4 , 6 , 7 {2, 4, 6\\} \cup {2, 3\\} \cup {3, 6, 7\\} = {2, 3, 4, 6, 7\\} 2,4,6∪2,3∪3,6,7=2,3,4,6,7 。

输入

每个测试包含多个测试用例。第一行包含测试用例的数量 t t t ( 1 ≤ t ≤ 100 1 \le t \le 100 1≤t≤100 )。测试用例说明如下。

每个测试用例的第一行都包含一个整数 n n n ( 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50 )。

接下来的 n n n行描述了集合 S 1 , S 2 , ... , S n S_1, S_2, \ldots, S_n S1,S2,...,Sn 。其中第 i i i 行包含一个整数 k i k_{i} ki ( 1 ≤ k i ≤ 50 1 \le k_{i} \le 50 1≤ki≤50 ) - S i S_{i} Si 中的元素个数,接下来是 k i k_{i} ki 个整数 s i , 1 , s i , 2 , ... , s i , k i s_{i, 1}, s_{i, 2}, \ldots, s{i, k_{i}} si,1,si,2,...,si,ki ( 1 ≤ s i , 1 s i , 2 ... s i , k i ≤ 50 1 \le s_{i, 1}s_{i, 2}\ldots s_{i, k_{i}} \le 50 1≤si,1si,2...si,ki≤50 ) - S i S_{i} Si 中的元素个数。

输出

针对每个测试用例,打印一个整数 : S S S 中可达到的最大元素个数,即 S ≠ S 1 ∪ S 2 ∪ ... ∪ S n S \neq S_{1} \cup S_{2} \cup \ldots \cup S_{n} S=S1∪S2∪...∪Sn .


题意简化一下就是:找到给出的集合,找出他们中的某个并集,使得这个并集的长度是小于所有集合的并集的长度的条件下是长度最大的一个并集。

假设最大的并集长度 就是 l e n len len,那么不能等于这个并集长度的最长的并集长度 就是 l e n − 1 len-1 len−1,也就是说我们就只需要找一个长度为 l e n − 1 len-1 len−1 的并集(如果存在的话),这个并集就满足了是最优解。

那么怎么找这样一个并集?如果一个集合中包含了一些数,那么只需要减少其中一个数,就可以得到一个长度减 1 1 1 的并集,根据给出的数据范围,我们只需要循环 1 1 1 到 50 50 50 这些数,然后再去枚举集合,如果某个集合中不含有这个数就合并上这个集合,并维护一个最终并集的长度的最大值。

Code:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 55;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;cin >> n;
        set<int>a[n];
        set<int>S;
        for(int i = 0;i < n;i++){
            int k;cin >> k;
            for(int j = 0;j < k;j++){
                int b;cin >> b;
                a[i].insert(b);
                S.insert(b);
            }    
        }
        int res = 0;
        int len = S.size();
        for(int i = 1;i <= 50;i++){
            S.clear();
            for(int j = 0;j < n;j++){
                if(a[j].count(i) == 0)
                    S.insert(a[j].begin(),a[j].end());
            }
            if(res < S.size() && S.size() < len){
                res = S.size();
            }
        }
        cout << res << endl;
    }
    return 0;
}
相关推荐
代码雕刻家18 分钟前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
雨中rain18 分钟前
算法 | 位运算(哈希思想)
算法
小飞猪Jay2 小时前
C++面试速通宝典——13
jvm·c++·面试
Kalika0-02 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
sp_fyf_20242 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
rjszcb3 小时前
一文说完c++全部基础知识,IO流(二)
c++
小字节,大梦想3 小时前
【C++】二叉搜索树
数据结构·c++
吾名招财3 小时前
yolov5-7.0模型DNN加载函数及参数详解(重要)
c++·人工智能·yolo·dnn
我是哈哈hh4 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
憧憬成为原神糕手4 小时前
c++_ 多态
开发语言·c++