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;
}
相关推荐
std787917 分钟前
用C++ 实现屏幕保护程序
开发语言·c++
CHANG_THE_WORLD21 分钟前
if条件语句 三目运算符 汇编分析
汇编·算法·条件语句·if 语句·汇编分析·条件语句汇编分析
tumu_C22 分钟前
无用知识研究:在trailing return type利用decltype,comma operator在对函数进行sfinae原创 [二]
开发语言·c++·算法
web安全工具库28 分钟前
告别刀耕火种:用 Makefile 自动化 C 语言项目编译
linux·运维·c语言·开发语言·数据库·算法·自动化
红糖生姜40 分钟前
P12874 [蓝桥杯 2025 国 Python A] 巡逻||题解||图论
c++·蓝桥杯·图论
海蓝可知天湛1 小时前
利用Genspark自定义智能体:算法竞赛测试数据反推与生成工具
算法·aigc
BothSavage1 小时前
Qwen3-VL-8B-Instruct推理测试transformer+sglang双版本
算法
尤超宇1 小时前
YOLOv3 目标检测算法核心技术
算法·yolo·目标检测
云泽8081 小时前
C/C++内存管理详解:从基础原理到自定义内存池原理
java·c语言·c++
cyclel1 小时前
散列表的小想法
算法