思路:二進制,位運算|,來標記狀態。比如一個集合裡面出現了 2 、4、 6 ,那就用二進制數101010 = (十進制) 2+8+32=42 ,來記錄該集合出現過!!,由於m值 <= 14,所以最多有 1<<14 個狀態,用這些二進制之間 | 運算,來生成新的集合。然後統計就得出答案。。看了題解做的,貌似很簡單的樣子,但是這也太難想了吧。。真心佩服那些自己想到的孩子們。。
AC代碼:
[cpp]
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
int a[1<<15];
int main()
{
int i,j,n,m;
while(~scanf("%d%d",&n,&m))
{
memset(a,0,sizeof(a));
int k,x,y;
int ans = 0;
while(n--)
{
scanf("%d",&k);
y = 0;
while(k--)
{
scanf("%d",&x);
y = y|(1<<x-1);
}
a[y] = 1;
for(i = 0;i <= 1<<14;i ++)
{
if(a[i])
a[i|y] = 1;
}
}
for(i = 1;i <= 1<<14;i ++)
if(a[i]) ans++;
printf("%d\n",ans);
}
}
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
int a[1<<15];
int main()
{
int i,j,n,m;
while(~scanf("%d%d",&n,&m))
{
memset(a,0,sizeof(a));
int k,x,y;
int ans = 0;
while(n--)
{
scanf("%d",&k);
y = 0;
while(k--)
{
scanf("%d",&x);
y = y|(1<<x-1);
}
a[y] = 1;
for(i = 0;i <= 1<<14;i ++)
{
if(a[i])
a[i|y] = 1;
}
}
for(i = 1;i <= 1<<14;i ++)
if(a[i]) ans++;
printf("%d\n",ans);
}
}