题意:有一个由编号0~n-1的n台计算机组成的网络,一共有n种服务,每台计算机上都运行着全部服务,
对于每台计算机,你可以选择停止一项服务,这个行为会导致与这台计算机和与他相连的其他计算机上的这项服务都停止(原来已经停止的继续保持停止状态)。
求最多能使多少个服务瘫痪(即没有任何一台计算机在运行这项服务)。
分析:用2进制表示每台电脑的集合有哪些电脑a[i],将这些集合用位运算求出若干a[i]的并集。
最后枚举每个状态和他的子集。
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<queue> #include<cmath> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define Mn 1<<16 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul u<<1 #define ur (u<<1)|1 using namespace std; typedef long long ll; int a[20]; int sum[Mn]; int dp[Mn]; int main() { int n,m,cas=0,x; while(scanf("%d",&n)) { if(n==0) break; cas++; for(int i=0;i<n;i++) { a[i]=1<<i; scanf("%d",&m); for(int j=1;j<=m;j++) { scanf("%d",&x); a[i]|=(1<<x); } } CLR(sum,0); for(int k=1;k<(1<<n);k++) for(int i=0;i<n;i++) if(k&(1<<i)) sum[k]|=a[i]; CLR(dp,0); int all=(1<<n)-1; for(int k=1;k<(1<<n);k++) for(int sk=k;sk;sk=(sk-1)&k) if(sum[sk]==all) dp[k]=max(dp[k],dp[k^sk]+1); printf("Case %d: %d\n",cas,dp[all]); } return 0; }