题意:有N头牛M个棚子,每头牛都有自己喜欢的棚子且每个棚子只能放一头牛,求方案数
Sample in
3 4
2 1 4
2 1 3
2 2 4
Sample out
4
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define l(x) ((x)<<1)
#define r(x) ((x)<<1|1)
#define lowbit(x) ((x)&(-(x)))
#define abs(x) ((x)>=0?(x):(-(x)))
#define ms(a,b) memset(a,b,sizeof(a))
#define NSYNC std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
using namespace std;
const int maxn = 2111111;
int dp[(1 << 20) + 5];
int ok[25][25];
int n, m, p, temp;
int main() {
NSYNC;
ms(ok, 0);
ms(dp, 0);
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> p;
for (int j = 0; j < p; j++) {
cin >> temp;
ok[i][temp - 1] = 1;
}
}
dp[0] = 1;
for (int i = 0; i < n; i++)
for (int j = (1 << m) - 1; j >= 0; j--) {//从后往前选
if (dp[j])//没有这行会超时
for (int k = 0; k < m; k++)
if (ok[i][k] && j != (j | (1 << k)))
dp[(j | (1 << k))] += dp[j];
dp[j] = 0;//选完之后把自身重置
}
int res = 0;
for (int i = 0; i < (1 << m); i++)
res += dp[i];
cout << res << "\n";
return 0;
}