ABC 289 C - Coverage(dfs)
半个多月没写题,连暴力dfs都忘记了,完蛋,烂菜地里了
https://atcoder.jp/contests/abc289/tasks/abc289_c
题目大意:
给定一个N,M个集合,然后分别给出M个集合里面的数字个数以及每个数,
问我们怎样选集合能达到1到N的每一个数字都存在,问我们这样的选法有多少种?求出方法数。
Sample Input 1
3 3
2
1 2
2
1 3
1
2
Sample Output 1
3
笑迷糊了,一开始范围都没看到,想半天。做题先看数据范围
N,M的范围都在10以内,所以只管妥妥暴力dfs,每个集合都进行选和不选即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18,MINN=31;
const LL N=1e6+10,M=4010;
const double PI=3.1415926535;
#define endl '\n'
vector<vector<LL>> a(N);
LL m,n,ans=0;
bool vis[N];
void dfs(LL idx)
{
if(idx>n)
{
set<LL> st;
for(int i=1;i<=n;i++)
{
if(vis[i])
{
for(int j=0;j<a[i].size();j++)
st.insert(a[i][j]);
}
}
if(st.size()==m) ans++;
return ;
}
//选
vis[idx]=true;
dfs(idx+1);
//不选
vis[idx]=false;
dfs(idx+1);
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
cin>>m>>n;
for(int i=1;i<=n;i++)
{
LL t;
cin>>t;
for(int j=1;j<=t;j++)
{
LL x;
cin>>x;
a[i].push_back(x);
}
}
dfs(1);
cout<<ans<<endl;
}
return 0;
}