很明显的状态压缩思想了。把全集分组,枚举每个集合的子集,看一个子集是否能覆盖所有的点,若能,则f[s]=max(f[s],f[s^s0]+1)。即与差集+1比较。
这种枚举集合的思想还是第一次遇到,果然太弱了。。。。~~~~
其中枚举集合
for(s0=s;s0;s0=(s0-1)&s)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=16; int pt[1<<N]; int cover[1<<N]; int f[1<<N]; int main(){ int n,x,icase=0; while(scanf("%d",&n),n){ int c,s; for(int i=0;i<n;i++){ scanf("%d",&c); s=(1<<i); for(int k=0;k<c;k++){ scanf("%d",&x); s|=(1<<x); } pt[i]=s; } memset(cover,0,sizeof(cover)); for(int i=0;i<(1<<n);i++){ for(int j=0;j<n;j++){ if((1<<j)&i){ cover[i]|=pt[j]; } } } memset(f,0,sizeof(f)); for(int s=0;s<(1<<n);s++){ f[s]=0; for(int s0=s;s0;s0=(s0-1)&s){ if(cover[s0]==(1<<n)-1) f[s]=max(f[s],f[s0^s]+1); } } printf("Case %d: %d ",++icase,f[(1<<n)-1]); } return 0; }