B. Sets and Union

题目:

样例:

输入
4
3
3 1 2 3
2 4 5
2 3 4
4
4 1 2 3 4
3 2 5 6
3 3 5 6
3 4 5 6
5
1 1
3 3 6 10
1 9
2 1 3
3 5 8 9
1
2 4 28

输出
4
5
6
0

思路:

        这里题目的意思是,要求合并尽可能多的集合,使它的集合大小最大,但是不能等于全部集合的合并。

        这里由于题目所给的范围较小,所以我们可以暴力枚举,其次,里面也有贪心的成分,这里我们换个思路,我们通过总的集合,根据总的集合中的某个元素,枚举不存在该元素的集合,并合并,就是不等于全部集合的合并,取个合并后的集合个数 max,就是答案。

代码详解如下:

#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#define endl '\n'
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define uset unordered_set
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;

inline void solve()
{	
	int t,ans = 0;
	
	umap<int,vector<int>>v;	// 记录每个集合
	
	uset<int>sum;	// 统计总集合
	
	cin >> t;	// t 为集合个数
	for(int i = 1;i <= t;++i)
	{
		int n;	// 集合大小
		cin >> n; 
		for(int j = 1;j <= n;++j)
		{
			int x;	// 集合元素
			cin >> x;
			
			// 记录该集合
			v[i].emplace_back(x);
			
			// 统计总集合元素
			sum.insert(x);
		}
	}
	
	// 开始 贪心删除
	for(auto now : sum)
	{	
		// 选择删除后的合并集合
		uset<int>tem;
		
		for(int i = 1;i <= t;++i)
		{
			// st 标记是否删除该集合
			bool st = false;
			
			// 遍历该集合
			for(auto j : v[i])
			{
				// 如果 sum 中的某个元素存在该集合
				// 那么我们选着的是删除这个集合
				// 所以无需添加
				if(now == j)
				{
					st = true;
					break;
				}
			}
			
			// 如果该集合不用删除,那么我们就添加该集合的元素
			if(!st)
			{
				for(auto j : v[i]) tem.insert(j);
			}	
		}
		// 判断选择删除这个元素后的,所有集合大小
		// 选择答案 合并集合个数最大,但不等于 sum 集合
		ans = max(ans,(int)tem.size());
	}
	
	cout << ans << endl;
}

int main()
{
//	freopen("a.txt", "r", stdin);
	___G;
	int _t = 1;
	cin >> _t;
	while (_t--)
	{
		solve();
	}
	return 0;
}

最后提交:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值