ACM模版
描述
题解
图论的问题我没有怎么深入学习,多数都是交给了队友去搞,所以看到这个题时,只知道是图上状压 DPDP,却不知道具体从何入手。
看了题解发现,原来形成不相交的简单环其实就是二分图的完美匹配,最后要求的就是二分图的完美匹配的个数取模。所以我们定义 dp[i][j]dp[i][j] 表示前 ii 个点匹配的状态为 jj 的方案数,则最后的结果便是 dp[n][(1<<n)−1]dp[n][(1 << n) - 1]。
代码
代码语言:javascript复制#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
const int MAXN = 22;
const int MAXM = (1 << 20) 5;
const int MOD = 998244353;
int n, m;
int dp[MAXN][MAXM];
vector<int> vi[MAXN];
template <class T>
inline void scan_d(T &ret)
{
char c;
ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9')
{
ret = ret * 10 (c - '0'), c = getchar();
}
}
int cal(int x)
{
int ret = 0;
while (x)
{
if (x & 1)
{
ret ;
}
x >>= 1;
}
return ret;
}
int main()
{
scan_d(n);
scan_d(m);
int u, v;
for (int i = 1; i <= m; i )
{
scan_d(u);
scan_d(v);
vi[u].push_back(v);
}
dp[0][0] = 1;
for (int i = 1; i <= n; i )
{
int t = 1 << n;
for (int j = 0; j < t; j )
{
if (cal(j) == i)
{
for (int k = 0; k < vi[i].size(); k )
{
v = vi[i][k];
if ((j >> (v - 1)) & 1)
{
dp[i][j] = (dp[i][j] dp[i - 1][j ^ (1 << (v - 1))]) % MOD;
}
}
}
}
}
printf("%dn", dp[n][(1 << n) - 1]);
return 0;
}