f[i][j] 表示考虑第i个点的匹配 ,前面的点匹配的集合为j的方案数
#include <bits/stdc++.h>
using namespace std;
#define int long long
//typedef long long ll;
typedef pair<int,int> pii;
#define x first
#define y second
#define pb push_back
#define inf 1e18
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
const int maxn=1e5+10;
const int mod=1e9+7;
int qmi(int a,int b) {
int res=1;
while(b) {
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
const int N=2e5+10;
int dr[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};
int n,k;
int m;
int f[1<<22][22];
int g[22][22];
void solve() {
cin>>n;
fer(i,0,n-1) {
fer(j,0,n-1) {
cin>>g[i][j];
}
}
f[0][0]=1;
for(int i=0; i<n; i++) {
for(int j=0; j<(1<<n); j++) {
if(__builtin_popcount(j)^i)continue;
for(int k=0; k<n; k++) {
if((j>>k&1)||!g[i][k])continue;
else f[j|(1<<k)][i+1]=(f[j|(1<<k)][i+1]+f[j][i])%mod;
}
}
}
cout<<f[(1<<n)-1][n];
}
signed main() {
IOS;
int _=1;
//cin>>_;
while(_--) solve();
return 0;
}
给定n个点完全二分图 求删除最小边权集合 仍存在完美匹配
hall定理 进行状压枚举即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
//typedef long long ll;
typedef pair<int, int> pii;
#define x first
#define y second
#define pb push_back
#define inf 1e18
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
int qmi( int a, int b ) {
int res = 1;
while( b ) {
if( b & 1 ) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
const int N = 2e5 + 10;
int dr[4][2] = {{ -1, 0}, {1, 0}, {0, -1}, {0, 1}};
int n, k;
int a[100][100];
int w[N];
int ans;
void solve() {
cin >> n;
fer( i, 0, n - 1 ) {
fer( j, 0, n - 1 ) {
cin >> a[i][j];
}
}
ans = ( int )( 1 << 30 );
for( int s = 1; s < ( 1 << n ); s++ ) {
for( int j = 0; j < n; j++ ) w[j] = 0;
for( int i = 0; i < n; i++ )if( s & ( 1 << i ) ) {
for( int j = 0; j < n; j++ ) {
w[j] += a[i][j];
}
}
sort( w, w + n );
int t = n - __builtin_popcount( s ) + 1;
int sum = 0;
for( int k = 0; k < t; k++ )sum += w[k];
ans = min( ans, sum );
}
cout << ans << endl;
}
signed main() {
//IOS;
int _ = 1;
//cin>>_;
while( _-- ) solve();
return 0;
}