题目
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 ≤ i < N) represents the description of node i.
The description for node i starts with an integer m (Number of neighbors for node i), followed by m
integers 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
Sample Output
Case 1: 3
Case 2: 2
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 ≤ i < N) represents the description of node i.
The description for node i starts with an integer m (Number of neighbors for node i), followed by m
integers 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
Sample Output
Case 1: 3
Case 2: 2
大意
有n台服务器,每个服务器上运行n个服务,有个黑客想去毁掉尽可能多的服务,黑客只能在每台服务器上毁掉某一个服务,同时和这台服务器直接相连的服务器的这个服务也会被毁掉,某个服务要在每个服务器上都毁掉了才算毁掉了,求最多能毁掉的服务。
解法
用i表示服务器的一个状态,i的二进制下某位是1表示黑客在这台服务器上毁掉了某个服务,0则没有,设f[i]=1表示i这个状态能毁掉一个服务,0则表示不行,然后还要排除一些多余的,比如f[101]是1,那么f[111]肯定是1了,但是既然能用少量的肯定会有少量的,所以f[111]是不应该被用到的,应该置为0。最后设dp[i]表示状态为i时的最大值,就有
if(f[j]==1&&(i&j)==j)
dp[i]=max(dp[i],1+dp[i^p[j]]);
dp[i]=max(dp[i],1+dp[i^p[j]]);
答案就是dp[1<<n];
代码
#include<cstdio>
#include<cstring>
int a[20][20],cnt[20],f[70000],vis[20],dp[70000],p[70000],cn;
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,i,j,cas=1;
while(scanf("%d",&n)&&n)
{
for(i=0;i<n;i++)
{
scanf("%d",&cnt[i]);
for(j=0;j<cnt[i];j++)
{
scanf("%d",&a[i][j]);
}
}
int lim=(1<<n);
memset(f,0,sizeof(f));
f[0]=0;
for(i=1;i<lim;i++)
{
memset(vis,0,sizeof(vis));
int tmp=i,pos=0;
while(tmp)
{
if(tmp&1)
{
vis[pos]=1;
for(j=0;j<cnt[pos];j++)
vis[a[pos][j]]=1;
}
tmp=tmp>>1;
pos++;
}
for(j=0;j<n;j++)
if(vis[j]==0)
break;
if(j==n)
f[i]=1;
}
cn=0;
for(i=1;i<lim;i++)
{
if(f[i]==0)
continue;
p[cn++]=i;
for(j=i+1;j<lim;j++)
{
if((j&i)==i)
{
f[j]=0;
}
}
}
memset(dp,0,sizeof(dp));
for(i=1;i<lim;i++)
{
for(j=0;j<cn;j++)
{
if((i&p[j])==p[j])
{
dp[i]=max(dp[i],1+dp[i^p[j]]);
}
}
}
printf("Case %d: %d\n",cas++,dp[lim-1]);
}
return 0;
}