51nod 1833 状压dp加一点图论
dp[i][j]:i代表前i个单位,j代表匹配的方案;
#include<stdio.h> #include<iostream> #include<vector> #include<string.h> #define ll long long #define MST(vis,x) memset(vis,x,sizeof(vis)) #define maxn 21 #define mod 998244353 using namespace std; int dp[maxn][(1<<20)+1]; vector<int>vec[22]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int a=1;a<=n;a++)vec[a].clear(); for(int a=1;a<=m;a++) { int x,y; scanf("%d%d",&x,&y); vec[x].push_back(y); } dp[0][0]=1; for(int i=1;i<=n;i++)//代表前i个 { for(int j=0;j<vec[i].size();j++)//枚举i与可匹配的数的匹配(用son代表) { for(int k=1;k<=(1<<n);k++)//枚举匹配模式 { if((k&(1<<vec[i][j]-1))&&dp[i-1][k-(1<<vec[i][j]-1)])//当匹配模式中有son时&&排除掉这个son和i,剩余的i-1个点在[k-(1<<son-1)]模式下是否有解 dp[i][k]=(dp[i][k]+dp[i-1][k-(1<<vec[i][j]-1)])%mod;//如果有解加起来即可 } } } printf("%d\n",dp[n][(1<<n)-1]);//输出前N个点在最大模式匹配下的结果
} return 0; }