题意:题意很费解,大意是有N台电脑,每台电脑有N(N<=16)个服务,一个黑客可以在每台电脑上跑一个(只能跑一个)让一种服务崩溃的病毒,并且这个病毒可以传播到跟他邻接的顶点,问最多这个黑客可以让多少个服务崩溃?(每台电脑上都是N个不同服务,每台电脑上跑的都是一样的服务,让一个服务崩溃是让所有的电脑上的这个服务崩溃)
分析:要想到题目对应的数学模型:把n个集合P1,p2,...,pn分成尽量多组使得每组中的所有集合的并集等于全集,这里集合Pi就是计算机i及其相邻计算机的集合,每组对应一种服务。书上说用二进制表示,我觉得有些地方还是不很理解。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <iostream> 3 using namespace std; 4 const int MAXN = (1<<16); 5 int p[20], cover[MAXN], f[MAXN]; 6 #define DEBUG 7 int main(){ 8 int n, m, i, j, x, cas=1; 9 while(scanf("%d", &n)!=EOF && n){ 10 for(i=0; i<n; i++){ 11 scanf("%d", &m); 12 p[i]=1<<i; 13 for(j=0; j<m; j++){ 14 scanf("%d", &x); 15 p[i] |=(1<<x); 16 } 17 } 18 int s; 19 for(s=0; s<(1<<n); s++){ 20 cover[s]=0; 21 for(i=0; i<n; i++) 22 if(s&(1<<i)) cover[s]|=p[i]; 23 } 24 f[0]=0; 25 int ALL = (1<<n) - 1; 26 for(s=1; s<(1<<n); s++){ 27 f[s] = 0; 28 for(int so=s; so; so=(so-1)&s) 29 if(cover[so]==ALL && f[s]<f[s^so]+1) f[s]=f[s^so]+1; //s^so是对应的补集还是什么别的?不理解啊 30 } 31 printf("Case %d: %d\n", cas++, f[ALL]); 32 } 33 return 0; 34 }