結果

問題 No.2504 NOT Path Painting
ユーザー suisensuisen
提出日時 2023-07-22 17:47:40
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 3,197 bytes
コンパイル時間 3,589 ms
コンパイル使用メモリ 116,476 KB
実行使用メモリ 8,696 KB
最終ジャッジ日時 2023-10-24 00:16:32
合計ジャッジ時間 5,897 ms
ジャッジサーバーID
(参考情報)
judge15 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

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

ソースコード

diff #

// TLE 区間DP 愚直

#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);

    auto solve = [&]{
        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;
    };

    int t;
    std::cin >> t;
    while (t --> 0) {
        solve();
    }

    return 0;
}
0