自学内容网 自学内容网

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=S1S2Sn .

† ^{\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 A1A2Ak 表示。例如, 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,62,33,6,7=2,3,4,6,7

输入

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

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

接下来的 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 1ki50 ) - 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 1si,1si,2si,ki50 ) - 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=S1S2Sn .


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

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

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

Code:

#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;
}

原文地址:https://blog.csdn.net/2302_79440616/article/details/137777710

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!