結果

問題 No.2504 NOT Path Painting
ユーザー suisensuisen
提出日時 2023-02-21 11:50:51
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
RE  
実行時間 -
コード長 2,844 bytes
コンパイル時間 2,074 ms
コンパイル使用メモリ 116,932 KB
実行使用メモリ 814,720 KB
最終ジャッジ日時 2024-12-15 16:30:47
合計ジャッジ時間 22,505 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 RE -
testcase_01 MLE -
testcase_02 MLE -
testcase_03 MLE -
testcase_04 MLE -
testcase_05 MLE -
testcase_06 MLE -
testcase_07 MLE -
testcase_08 MLE -
testcase_09 MLE -
testcase_10 MLE -
testcase_11 MLE -
testcase_12 MLE -
testcase_13 MLE -
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <deque>
#include <iostream>
#include <tuple>
#include <vector>

#include <atcoder/modint>

using mint = atcoder::modint998244353;

int edge_num(int n) {
    return (n * (n + 1)) >> 1;
}

auto find_path_on_tree(const std::vector<std::vector<int>> &g, int u, int v) {
    std::vector<int> res;
    auto dfs = [&](auto dfs, int cur, int par) -> bool {
        res.push_back(cur);
        if (cur == v) return true;
        for (int nxt : g[cur]) if (nxt != par and dfs(dfs, nxt, cur)) return true;
        res.pop_back();
        return false;
    };
    dfs(dfs, u, -1);
    return res;
}

#include <algorithm>
#include <map>

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;
    std::vector<std::vector<int>> g(n);
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        std::cin >> u >> v;
        --u, --v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    const int m = edge_num(n);

    const mint inv_m = mint(m).inv();

    std::map<std::pair<int, int>, std::vector<int>> paths;
    std::map<std::pair<int, int>, std::vector<int>> compl_paths;
    std::map<std::vector<int>, std::pair<int, int>> rev_paths;
    for (int x = 0; x < n; ++x) for (int y = 0; y <= x; ++y) {
        std::vector<int> path = find_path_on_tree(g, x, y);
        std::sort(path.begin(), path.end());

        std::vector<int> compl_path;
        for (int i = 0, j = 0; i < n; ++i) {
            if (j < int(path.size()) and path[j] == i) {
                ++j;
                continue;
            }
            compl_path.push_back(i);
        }
        paths[std::make_pair(x, y)] = path;
        rev_paths[path] = std::make_pair(x, y);
        compl_paths[std::make_pair(x, y)] = compl_path;
    }

    std::map<std::pair<int, int>, mint> dp;
    auto rec = [&](auto rec, int x, int y) -> mint {
        if (auto it = dp.find(std::make_pair(x, y)); it != dp.end()) {
            return it->second;
        }

        mint a = 1, b = 1;
        std::vector<int> path = paths[std::make_pair(x, y)];
        for (const auto &[_, compl_path] : compl_paths) {
            std::vector<int> next_path;
            std::set_difference(path.begin(), path.end(), compl_path.begin(), compl_path.end(), std::back_inserter(next_path));
            if (next_path.size()) {
                if (next_path.size() == path.size()) {
                    a -= inv_m;
                } else {
                    auto [nx, ny] = rev_paths[next_path];
                    b += inv_m * rec(rec, nx, ny);
                }
            }
        }
        return dp[std::make_pair(x, y)] = b * a.inv();
    };

    mint ans = 1;
    for (int x = 0; x < n; ++x) for (int y = 0; y <= x; ++y) {
        ans += rec(rec, x, y) * inv_m;
    }
    std::cout << ans.val() << std::endl;

    return 0;
}
0