蓝题?错误的,这是黄题。
枚举第 $i$ 个左部点,枚举与它匹配的右端点 $j$,判定是否能加入即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 25, M = (1 << 21) + 15, mod = 1e9 + 7;
int n, a[N][N];
int dp[M];
int pop(int S) {
int res = 0;
while (S) res += S & 1, S >>= 1;
return res;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) scanf("%d", &a[i][j]);
dp[0] = 1;
for (int i = 0; i < n; i++) {
for (int S = 0; S < (1 << n); S++) {
if (pop(S) != i) continue;
for (int j = 1; j <= n; j++) {
if (!a[i + 1][j]) continue;
if (S & (1 << j - 1)) continue;
(dp[S | (1 << j - 1)] += dp[S]) %= mod;
}
}
}
printf("%d\n", dp[(1 << n) - 1]);
return 0;
}