题意:
有n个集合,问你能否在L次内把所有集合都删去,如果两个或者更多集合内含有一个相同的数,则这些集合可以同时删除
每个集合中的元素小于10,L<=5,n<=30
分析:
由于数据范围都比较小,很容易想到搜索
很容易想到可以枚举当前集合应该删除哪个数,如果下一个集合中已经出现过了这个数,则跳过下一个集合,可以选择的删除的数不超过5个
每个集合中最多有10个数能被选择,所以时间复杂度也就为10^5*n,乘以n是因为要判断需不需要从当前这个集合中删除一个数
貌似还有一种贪心的做法,每次删除的这个数一定是在未删除的集合中出现次数最多,假设在前L-1次成立,则最后一次选择删除出现次数最多一定比出现次数不是最多更优
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ll;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
bool flag1;
int n,L;//a表示取了哪几个数
int count1[35],number[35][12];
int vis[305];
int num1=0;
bool judge(int num){
for(int i=1;i<=count1[num];i++)
if(vis[number[num][i]]==1)
return true;
return false;
}
void dfs(int num,int d){
if(num>n){ //搜索到了哪一个集合
flag1=true;
return ;
}
if(judge(num))
dfs(num+1,d);
if(flag1)
return ;
if(d>L+1) //使用了5个的时候d为6
return ;
for(int i=1;i<=count1[num];i++){ //这一个集合中取哪一个数
vis[number[num][i]]=1;
dfs(num+1,d+1); //count2表示用了几个数
if(flag1)
return ;
vis[number[num][i]]=0;
}
}
int main(){
int _;
scanf("%d",&_);
while(_--){
scanf("%d%d",&n,&L);
memset(vis,0,sizeof(vis));
flag1=false;
for(int i=1;i<=n;i++){
scanf("%d",&count1[i]);
for(int j=1;j<=count1[i];j++)
scanf("%d",&number[i][j]);
}
dfs(1,1);
if(flag1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}