题意:有n台计算机n个服务,每个计算机有相关联的计算机,攻击之后,相关联的也受影响。我们只能让某一个计算机停止某一个服务,如何使尽量多的服务完全瘫痪(没有任何计算机有该服务)
就是有n个集合P1,P2....Pn,每个集合表示的与之相关联的计算机,分成尽量多的一组,使并集为全集(这样这些计算机停止一项服务就行)
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mem(name,value) memset(name,value,sizeof(name))
#define FOR(i,n) for(int i=1;i<=n;i++)
using namespace std;
const int maxn = 17;
const int maxm = 1<<17;
int cover[maxm],p[maxn],f[maxm];
int main(){
int n,m,x,kase=0;
while(~scanf("%d",&n) && n){
for(int i=0;i<n;i++){
scanf("%d",&m);
p[i] = (1<<i);
while(m--){scanf("%d",&x); p[i] |= (1<<x);}
}
//for(int i=0;i<n;i++) printf("%d\n",p[i]);
for(int S=0;S<(1<<n);S++){ //cover(S)表示集合S中所有pi的并集。
cover[S] = 0;
for(int i=0;i<n;i++)
if(S & (1<<i)) cover[S] |= p[i];
}
int ALL = (1<<n)-1;
for(int S=0;S<(1<<n);S++){
f[S] = 0;
for(int S0 = S; S0 ; S0 = (S0-1)&S)<span style="white-space:pre"> </span>//枚举子集
if(cover[S0]==ALL) f[S] = max(f[S],f[S^S0]+1);
}
printf("Case %d: %d\n",++kase,f[ALL]);
}
return 0;
}