オリジナルタイトルポータル
質問の説明の意味:
nおよびm縁と点、次のm行の各X与え、二つのリングのY点は、通信、図の出力を表します。
トピック分析:
データルックのn <= 19、すぐに録画状態圧力DPを考えるように
[I] [j]をfを設定する状態をi実証があったときに、2つのノードを同じ時間に、エンドポイントは、私は、次のノードの列挙にリングlowbit最小点で、状態のための経路の出発点Jであることを示しリングは、無向グラフの場合ので、そこになります::
- それは二回二方向にトラバース記録されますので、リング
- 一の側及び両端点は、(2つの点が起因リングの誤判断にお互いに達することができる)不正リング現れます
したがって、最終的な答えANS =(ANS - M)/ 2
コード:
/* Codeforces11D -- A Simple Task */
#include <bits/stdc++.h>
#define int long long
int n, m, ans;
int f[1 << 19][19];
bool mp[25][25];
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
f = (ch == '-') ? -1 : 1, ch = getchar();
while (isdigit(ch))
x = x * 10 + (ch - '0'), ch = getchar();
return x * f;
}
main()
{
// freopen("in.txt", "r", stdin);
n = read(), m = read();
int x, y;
int MaxState = 1 << n;
for (int i = 1; i <= m; i++)
x = read() - 1, y = read() - 1, mp[x][y] = mp[y][x] = true;
for (int i = 0; i < n; i++)
f[1 << i][i] = 1; /* 初始化 */
for (int i = 1; i <= MaxState; i++)
for (int j = 0; j < n; j++)
{
if (!f[i][j]) /* 无环图 */
continue;
for (int k = 0; k < n; k++) /* 枚举下一节点 */
{
if (!mp[j][k]) /* 不连通就直接跳过 */
continue;
if ((i & -i) > (1 << k)) /* lowbit > (1 << k)表示k点编号小于i点编号,但是起点不可以更改 */
continue;
if ((1 << k) & i) /* 构成一个环 */
{
if ((1 << k) == (i & -i)) /* 这个环回到了起点 */
ans += f[i][j];
}
else
f[i | (1 << k)][k] += f[i][j]; /* 状态转移 */
}
}
std::cout << (ans - m) / 2 << '\n';
}