洛谷-寻找团伙

题目描述

世界局势风云变幻,你想办一件大事。办事自然要有人参与,你能从 n 个人里面挑选一部分人共襄盛举。

要办这件事,一共涉及 k 方面的能力,例如游说他人的能力、玩游戏的能力、睡觉的能力。每位人士都会具备某一些能力,例如机器猫就可能擅长睡觉、擅长玩游戏,而不擅长游说他人。

你的计划很宏伟,因此你希望团队拥有很全面的能力。不幸的是,如果团队中有偶数个人拥有同一类能力,那么他们就会分成两派,争执不下,导致整个团队丧失这方面的能力。相应地,如果这项能力只有奇数个人拥有,那么他们总能形成一个多数派,帮团队去做这方面的工作。

需要注意的是,团队拥有的每一项能力,对计划的成功率的贡献是不一样的。第一项能力最重要,它的权重是 2^k−1;第二项能力的权重是 2^k−2;依次类推。第 k 项能力最不重要,权重只有 1。

计划的成功率得分,即是团队拥有的所有能力对应的权重之和

你希望计划成功率最大。因此,你需要选出合适的人士,来参与到你的宏图伟业中。

输入格式

第一行,两个正整数 n,k。分别表示供你挑选的人的数量,以及能力的种类数。
接下来 n 行,每行表示每个人拥有的能力。这一行首先有一个整数 c,表示该人士拥有多少种能力;接下来是 c 个 [1,k] 之间的正整数,表示该人士拥有哪些能力。

输出格式

仅一行,一个整数,表示计划的成功率得分。

输入输出样例

输入 #1

5 5
1 1
1 2
1 3
1 4
1 5

输出 #1

31

输入 #2

3 5
3 1 2 3
4 2 3 4 5
2 3 4

输出 #2

28

总体思路:

1.根据每个人向对应的能力记录下其对应的分值

2.对于每个人,可以有两种状态:

        选择这个人,则加上他对应的分值;

        不选这个人,则分数不变;

3.如果选择过的人数超过了总人数,直接返回

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
ull n, k, a[22], ans;

//dep:表示已经选择了的人数,now表示选择之后的分数
inline void dfs(ull dep, ull now) 
{
    //如果选择的人数超过n个人,直接返回结果
	if(dep > n) 
	{
		ans = max(ans, now);
		return;
	}
	//员工的能力有选和不选两种方式,
	dfs(dep + 1, now ^ a[dep]);//选这个人,异或上他的分值
	dfs(dep + 1, now);//不选
}
int main() 
{
	cin >> n >> k;
	for(ull i = 1, c; i <= n; i++) 
	{
		cin >> c;
		for(ull j = 1, x; j <= c; j++) 
		{
			cin >> x;
			//记录他能力相对应的分值
			a[i] |= (1ull << (k - x)); 
		}
	}
	dfs(0, 0);
	cout << ans;
	return 0;
}

并查集是一种数据结构,可以有效地解决团伙问题。团伙问题指的是在一个群体中,找出其中的团伙关系。举个例子,假设有一群人,其中有些人是朋友,有些人是陌生人,现在需要找出所有的朋友团伙。这个问题可以用并查集来解决。 具体实现过程如下: 1. 初始化并查集,将每个人看作一个单独的团伙,即每个人的父节点都是自己。 2. 遍历所有的朋友关系,将每个朋友关系所在的两个人合并到同一个团伙中。合并的过程中,需要找到两个人所在团伙的根节点,将其中一个根节点的父节点指向另一个根节点。 3. 遍历所有的人,统计每个团伙的人数。具体方法是遍历每个人,找到该人所在团伙的根节点,然后统计该根节点下所有子节点的个数。 4. 输出所有团伙的人数。 下面是并查集实现团伙问题的示例代码(假设已经读入了朋友关系列表friend_list): ```python # 初始化并查集 parent = {} for i in range(len(friend_list)): parent[i] = i # 合并朋友关系所在的团伙 for f1, f2 in friend_list: root1 = find_root(parent, f1) root2 = find_root(parent, f2) if root1 != root2: parent[root1] = root2 # 统计每个团伙的人数 group_sizes = {} for i in range(len(friend_list)): root = find_root(parent, i) if root not in group_sizes: group_sizes[root] = 1 else: group_sizes[root] += 1 # 输出每个团伙的人数 for root, size in group_sizes.items(): print("团伙{}有{}个人".format(root, size)) # 找到节点的根节点 def find_root(parent, node): while parent[node] != node: node = parent[node] return node ``` 这个代码实现了一个简单的并查集,并可以用来解决团伙问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值