状压DPhdu6006
#include<iostream>
#include<cstring>
using namespace std;
int h[1<<10][1<<10];
int t,n,m,c[11],d[11],a[11][3],b[11][2],vis[11][101],ans;
void dfs(int now,int pro,int eng){
if(now==n)
{
return;
}
if(h[pro][eng]+n-now<=ans) return;
for(int i=0;i<(1<<m);i++){
if(i&eng) {
continue; //这个eng考虑过了
}
int cnt=0;
for(int j=0;j<m;j++){
int temp=0;
if(i&(1<<j)){
for(int k=0;k<d[j];k++){
int temp=b[j][k];
// printf("%d %d %d %d %d
",i,j,temp,cnt,vis[now][temp]);
if(vis[now][temp]==1){
vis[now][temp]=2;
cnt++;
}
}
}
}
if(cnt==c[now]){
h[pro|(1<<now)][eng|i]=h[pro][eng]+1;
ans=max(ans,h[pro|(1<<now)][eng|i]);
dfs(now+1,pro|(1<<now),eng|i);
}
for(int j=0;j<m;j++){
if(i&(1<<j)){
for(int k=0;k<d[j];k++){
int temp=b[j][k];
if(vis[now][temp]==2){
vis[now][temp]=1;
}
}
}
}
}
ans=max(ans,h[pro][eng]);
dfs(now+1,pro,eng);
}
int main(){
scanf("%d",&t);
int T=0;
while(t--){
ans=0;
memset(h,-1,sizeof(h));
h[0][0]=0;
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&c[i]);
for(int j=0;j<c[i];j++){
scanf("%d",&a[i][j]);
vis[i][a[i][j]]=1;
}
}
for(int i=0;i<m;i++){
scanf("%d",&d[i]);
for(int j=0;j<d[i];j++){
scanf("%d",&b[i][j]);
}
}
dfs(0,0,0);
printf("Case #%d: %d
",++T,ans);
}
return 0;
}