来自http://www.cnblogs.com/lonelycatcher/archive/2011/05/27/2060158.html
这题就是用一个二进制数保存一个集合的元素 比如一个集合中有两个元素 1 3 那就用5 (101)表示这个集合
就是用0 1 来表示这个集合中一个数存不存在 再比如 一个集合有 三个元素 1 4 5 就在这几个位子上标为1,那就
用25 (11001)来表示这个集合!在借助于位运算的或( | )就可已达到合并集合的目的,比如一个集合(1 4 )
和一个集合(1 2 3)进行合并 那就是 (9)1001 | 111(7)=1111 就是15 这样就将重复的部分覆盖了。新的集合就用15来表示!最大就是(11111111111111)2^15-1来表示一个集合!
#include<stdio.h>
#include<string.h>
int s[1<<15];
int n,m,k,element;
int i,j;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int ans=0;
memset(s,0,sizeof(s));
while(n--)
{
int set=0;
scanf("%d",&k);
while(k--)
{
scanf("%d",&element); //将集合转换成二进制,储存在数组s中
set=set|(1<<(element-1));
}
s[set]=1; //储存在s中
for( j=0;j<=(1<<14);j++) //根据 前面的描述求不同集合的并集
{
if(s[j]){s[set|j]=1;}
}
}
for( i=0;i<=1<<14;i++) //统计并集的个数,即为所求得可以组成的集合数
{
if(s[i]){ans++;}
}
printf("%d
",ans);
}
return 0;
}
总之 这方法真是太巧了