我们称简单有向图 � , � G,H 本质相同,当且仅当: 对于任意点对 ( � , � ) (u,v),若在图 � G 中从 � u 出发能走到 � v,则在图 � H 中从 � u 出发能走到 � v。反之若在图 � H 中从 � u 出发能走到 � v,则在图 � G 中从 � u 出发也能走到 � v。 若对于简单有向图 � G,不存在其他简单有向图 � H 与其本质相同,则我们称图 � G 为 单图。 � T 次询问,每次询问给定一个正整数 � n,请你回答 � n 个点的有标号单图数。c++代码
时间: 2024-02-15 14:02:49 浏览: 67
以下是使用动态规划算法求解的 C++ 代码:
```cpp
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 20;
const int MAXS = 1 << MAXN;
const int MOD = 998244353;
int n;
int g[MAXN][MAXN];
int dp[MAXS];
bool vis[MAXS];
int dfs(int s) {
if (vis[s]) {
return dp[s];
}
vis[s] = true;
if (s == (1 << n) - 1) {
dp[s] = 1;
return dp[s];
}
int u;
for (u = 0; u < n; u++) {
if ((s & (1 << u)) == 0) {
break;
}
}
int &ans = dp[s];
for (int v = u + 1; v < n; v++) {
if ((s & (1 << v)) == 0 && g[u][v]) {
ans = (ans + dfs(s | (1 << u) | (1 << v))) % MOD;
}
}
return ans;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> g[i][j];
}
}
memset(vis, false, sizeof(vis));
cout << dfs(0) << endl;
return 0;
}
```
其中,`g[i][j]` 表示从顶点 `i` 到顶点 `j` 是否存在一条有向边。`dp[s]` 表示状态为 `s` 的有标号单图数。`vis[s]` 表示状态 `s` 是否已经被访问过。在 `dfs` 函数中,通过枚举两个未被访问的顶点 `u` 和 `v`,如果从 `u` 到 `v` 存在一条有向边,则递归计算状态 `s | (1 << u) | (1 << v)` 的有标号单图数,并累加到答案中。最后返回状态为 0 的有标号单图数即可。
阅读全文