题意:
有n台计算机,每台计算机都运行n个服务器,让你去破坏,每台计算机你能破坏一种服务,它和它的邻居们的该台服务都会被破坏,所有计算机的这种服务都被破坏才算这项服务成功破坏,让你求最大能成功破坏多少种服务。
思路:
该问题可转为:把n个集合goup1,2,…n分成尽量多组,使每组中所有集合的并集等于全集。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int group[18];
int ans[1 << 17], cover[1 << 17];
int n, m;
int main()
{
int cas = 0, x;
while (~scanf("%d", &n) && n)
{
for (int i = 0; i<n; i++)
{
int st = 1 << i;
scanf("%d", &m);
for (int j = 0; j<m; j++)
{
scanf("%d", &x);
st|= 1 << x;
}
group[i] = st;//包含计算机i及i的邻居
}
int Max = (1 << n) - 1, S, S0;
for (S = 1; S <= Max; S++)
{
cover[S] = 0;
for (int i = 0; i < n; i++)
if (S&(1 << i))
cover[S] |= group[i];//S覆盖到的范围
}
for (S = 1; S <= Max; S++){
ans[S] = 0;
for ( S0 = S; S0; S0 = (S0 - 1)&S)//枚举S的子集
if (cover[S0] == Max) //S0可覆盖全部才能满足要求
ans[S] = max(ans[S], ans[S^S0] + 1);//S0为S的一个部分
}
printf("Case %d: %d\n", ++cas, ans[S - 1]);
}
}