Problem
H Hackers’
Crackdown
Miracle Corporations has a number of system services running in a
distributed computer system which is a prime target for hackers.
The system is basically a set of N computer
nodes with each of them running a set of N services.
Note that, the set of services running on every node is same
everywhere in the network. A hacker can destroy a service by
running a specialized exploit for that service in all the
nodes.
One day, a smart hacker collects necessary exploits for all
these N services and
launches an attack on the system. He finds a security hole that
gives him just enough time to run a single exploit in each
computer. These exploits have the characteristic that, its
successfully infects the computer where it was originally run and
all the neighbor computers of that node.
Given a network description, find the maximum number of services
that the hacker can damage.
Input
There will be multiple test cases in the input file. A test case
begins with an integer N
(1<=N<=16),
the number of nodes in the network. The nodes are denoted by 0
to N
- 1. Each
of the following N lines
describes the neighbors of a node. Line i
(0<=irepresents
the description of node i.
The description for node i starts
with an integer m (Number
of neighbors for node i),
followed by mintegers
in the range of 0 to N
- 1,
each denoting a neighboring node of node i.
The end of input will be denoted by a case
with N = 0. This case should not be
processed.
Output
For each test case, print a line in the format, “Case X: Y”,
where X is
the case number & Y is
the maximum possible number of services that can be
damaged.
Sample
Input
|
|
3
2 1
2
2 0
2
2 0
1
4
1
1
1
0
1
3
1
2
0
|
Output for
Sample Input
Case 1:
3
Case 2:
2
题意: 现在有n个服务,
都运行在n台计算机上, 选择某台计算机上的一项服务停止, 与它相邻的计算机
上, 该服务也会停止的, 现在要你让尽量多的服务完全停止.
(n台计算机上都不运行该服务).
解题思路:
1. 这题思路, 因为n<=16,
可以采用枚举组合的情况.
设状态dp[S]表示当选择部分计算机的集合S, 最多可以停止的服务个数.
状态方程:
dp[S] = max(dp[S], dp[S0]+1)
其中S0是S的子集,
并且满足S0集合可以覆盖全部的计算机.
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 20
int n;
int p[MAX], cover[1<<MAX];
int dp[1<<MAX];
inline int max(int a, int b)
{
return a
> b ? a : b;
}
int main()
{
//
freopen("input.txt", "r", stdin);
int caseNum
= 1;
while(scanf("%d", &n) !=
EOF)
{
if(n == 0) break;
int num, v;
for(int i = 0; i < n; ++i)
{
scanf("%d",
&num);
p[i] =
(1<<i);
for(int j =
0; j < num; ++j)
{
scanf("%d",
&v);
p[i] |=
(1<<v);
}
}
for(int i = 0; i <
(1<<n); ++i)
{
cover[i] =
0;
for(int j =
0; j < n; ++j)
{
if(i&(1<<j))
cover[i] |=
p[j];
}
}
dp[0] = 0;
int all = (1<<n)-1;
for(int s = 1; s <
(1<<n); ++s)
{
dp[s] =
0;
for(int s0 =
s; s0 != 0; s0 = (s0-1)&s)
{
if(cover[s0]
== all)
dp[s] =
max(dp[s], dp[s^s0]+1);
}
}
printf("Case %d: %d\n", caseNum++, dp[all]);
}
return
0;
}