POJ 2443 Set Operation [bitset]

题目

You are given N sets, the i-th set (represent by S(i)) have C(i) element (Here “set” isn’t entirely the same as the “set” defined in mathematics, and a set may contain two same element). Every element in a set is represented by a positive number from 1 to 10000. Now there are some queries need to answer. A query is to determine whether two given elements i and j belong to at least one set at the same time. In another word, you should determine if there exist a number k ( 1 ≤ k ≤ N ) k (1\le k \le N) k(1kN) such that element i belongs to S(k) and element j also belong to S(k).

题目大意

给定n个集合,然后给出两个数据,判断是否至少有一个集合同时包含这两个数据。

input

First line of input contains an integer N ( 1 ≤ N ≤ 1000 ) N (1 \le N \le 1000) N(1N1000), which represents the amount of sets. Then follow N lines. Each starts with a number C(i) ( 1 ≤ C ( i ) ≤ 10000 ) (1 \le C(i) \le 10000) (1C(i)10000), and then C(i) numbers, which are separated with a space, follow to give the element in the set (these C(i) numbers needn’t be different from each other). The N + 2 line contains a number Q ( 1 ≤ Q ≤ 200000 ) (1 \le Q \le 200000) (1Q200000), representing the number of queries. Then follow Q lines. Each contains a pair of number i and j ( 1 ≤ i , j ≤ 10000 , a n d i m a y e q u a l t o j ) (1 \le i, j \le 10000, and i may equal to j) (1i,j10000,andimayequaltoj), which describe the elements need to be answer.

output

For each query, in a single line, if there exist such a number k, print “Yes”; otherwise print “No”.

Sample input

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

Sample output

Yes
Yes
No
No

分析

首先,因为集合数目最大为1000,每个集合中元素最多为10000,应对规模为200000的查询,采用set对每个集合进行处理并判定,必然会导致超时。但是因为数据的规模在10000以下,可以尝试建立一个二维数组,若是在 i i i集合中有 j j j,则可以将 a [ i ] [ j ] a[i][j] a[i][j]置为1,在判断时,若两个数据在同一行中对应位置为1,则说明在同一个集合中。
但是对于数组而言,不论用int还是bool都开不出 1000 × 10000 1000\times10000 1000×10000大小的空间。由此我们可以使用bitset位图进行压位处理。
bitset是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1位(bit)。当输入一个数的时候,对该数的对应下标采用set()函数置为1。
本题解题时,以每一列表示一个集合,每一行表示该数据是否在某一个集合中。那么,对两个需要检验的数据所在行进行按位&操作,若最后的结果不全为零,即可说明两个数据至少在一个集合中同时出现过。

代码

#include<iostream>
#include<bitset>

using namespace std;

int main(){
	bitset<1001> sets[10000];//建立二维数组
	int n,c,q,a,b,m;
	scanf("%d",&n);
	for(int i = 0;i<n;++i){
		scanf("%d",&c);
		for(int j = 0;j<c;++j){
			scanf("%d",&m);
			sets[m].set(i);//数据m出现在集合i中
		}
	}
	scanf("%d",&q);
	for(int i = 0;i<q;++i){
		scanf("%d %d",&a,&b);
		bool flag = false;
		if((sets[a]&sets[b]).any())//判断是否还有1的存在
			printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

registor11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值