这题还是挺不错的,第一个突破点就是n很大但是m很小,所以能组成的集合最多有2^14种的,枚举这每一种能否构成即可。刚开始的时候是用set存每一个数的,超时,略加改进,用位存储就过掉了。不过我还是算蹭过的,600多ms,应该还能继续用位运算优化。
/* * hdu3306/win.cpp * Created on: 2012-10-27 * Author : ben */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> #include <stack> #include <string> #include <vector> #include <deque> #include <list> #include <functional> #include <numeric> #include <cctype> using namespace std; const int MAXN = 105; int sets[MAXN]; bool used[MAXN]; int N, M, ans; void init() { int J, t; fill(sets, sets + N, 0); for(int i = 0; i < N; i++) { scanf("%d", &J); for(int j = 0; j < J; j++) { scanf("%d", &t); sets[i] += (1 << t); } } } bool judge_state(int state) { fill(used, used + N, true); int s = state; for(int i = 1; i <= M; i++) { if(s % 2 == 0) { for(int j = 0; j < N; j++) { if((sets[j] & (1 << i))) { used[j] = false; } } } s >>= 1; } s = state; for(int i = 1; i <= M; i++) { if(s % 2 == 1) { int j = 0; for(; j < N; j++) { if(used[j] && (sets[j] & (1 << i))) { break; } } if(j >= N) { return false; } } s >>= 1; } return true; } int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif while(scanf("%d%d", &N, &M) == 2) { init(); ans = 0; for(int state = 1; state < (1 << M); state++) { if(judge_state(state)) { ans++; } } printf("%d\n", ans); } return 0; }