第一想法是搜索,但有n^n种状态。
本题的数学模型可以是每台电脑和相连的电脑看作一个集合。p1,p2.....pn。要使停止的服务越多。要求从p中选出最多的字集,是每个子集的并集
为n台电脑都有。每个pi可以用整数的二进制位的状态表示。用dp,dp(i)=max{dp(i-j)}+1,i为是否选p1,p2....pn的状态表示,j是i的子集。
实现需要枚举i的子集。
/*
uva 11825
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
int main(int argc, char const *argv[])
{
// freopen("input","r",stdin);
int n;
int q=0;
while(scanf("%d",&n),q++,n)
{
int dp[1<<n];
int A[1<<n];
memset(A,false,sizeof(A));
memset(dp,false,sizeof(dp));
int p[20];
int v=n;
for(int i=0;i<n;i++)
{
int m;
scanf("%d",&m);
p[i]=1<<i;
for(int j=0;j<m;j++)
{
int t;
scanf("%d",&t);
p[i]|=1<<t;
}
}
for(int i=0;i<1<<n;i++)
{
int t=i;
for(int j=0;j<n;j++,t=t>>1)//不要写成t>>1
if(t & 1) A[i]|=p[j];
// printf("%da\n",A[i] );
}
int s=(1<<n)-1;//一定要加()
for(int i=0;i<=s;i++)
{
if(i==0)
{
dp[i]=0;
continue;
}
int j=i;
do//枚举子集
{
if(A[j]==s)
{
// printf("%d\n",j );
dp[i]=dp[i]>dp[i & ~j]+1 ? dp[i]:dp[i & ~j]+1;
}
j=(j-1) & i;
}while(j!=i);
}
printf("Case %d: %d\n",q,dp[s] );
}
return 0;
}