【Codeforces 11D]単純タスク

オリジナルタイトルポータル

質問の説明の意味:

nおよびm縁と点、次のm行の各X与え、二つのリングのY点は、通信、図の出力を表します。

トピック分析:

データルックのn <= 19、すぐに録画状態圧力DPを考えるように

[I] [j]をfを設定する状態をi実証があったときに、2つのノードを同じ時間に、エンドポイントは、私は、次のノードの列挙にリングlowbit最小点で、状態のための経路の出発点Jであることを示しリングは、無向グラフの場合ので、そこになります::

  1. それは二回二方向にトラバース記録されますので、リング
  2. 一の側及び両端点は、(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';
}

おすすめ

転載: www.cnblogs.com/wyctstf/p/11372158.html