結果
問題 | No.768 Tapris and Noel play the game on Treeone |
ユーザー | lumc_ |
提出日時 | 2019-08-21 11:08:06 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 103 ms / 2,000 ms |
コード長 | 7,166 bytes |
コンパイル時間 | 1,637 ms |
コンパイル使用メモリ | 136,032 KB |
実行使用メモリ | 18,800 KB |
最終ジャッジ日時 | 2024-10-08 06:05:52 |
合計ジャッジ時間 | 5,074 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 3 ms
5,248 KB |
testcase_04 | AC | 3 ms
5,248 KB |
testcase_05 | AC | 3 ms
5,248 KB |
testcase_06 | AC | 3 ms
5,248 KB |
testcase_07 | AC | 57 ms
12,288 KB |
testcase_08 | AC | 27 ms
7,808 KB |
testcase_09 | AC | 32 ms
8,832 KB |
testcase_10 | AC | 24 ms
7,552 KB |
testcase_11 | AC | 100 ms
17,408 KB |
testcase_12 | AC | 99 ms
17,536 KB |
testcase_13 | AC | 95 ms
17,024 KB |
testcase_14 | AC | 95 ms
17,024 KB |
testcase_15 | AC | 103 ms
17,920 KB |
testcase_16 | AC | 91 ms
17,920 KB |
testcase_17 | AC | 93 ms
18,176 KB |
testcase_18 | AC | 83 ms
18,800 KB |
testcase_19 | AC | 85 ms
17,932 KB |
testcase_20 | AC | 78 ms
17,428 KB |
testcase_21 | AC | 71 ms
16,436 KB |
20evil_special_uni1.txt | AC | 94 ms
17,480 KB |
20evil_special_uni2.txt | AC | 88 ms
16,992 KB |
ソースコード
// includes {{{ #include <algorithm> #include <cassert> #include <cmath> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <random> #include <set> #include <stack> #include <tuple> #include <vector> // #include<deque> // #include<multiset> // #include<bitset> // #include<cstring> // #include<bits/stdc++.h> // }}} using namespace std; using ll = long long; /// --- ReRooting {{{ /// #include <cassert> #include <functional> #include <queue> #include <stack> #include <tuple> #include <utility> #include <vector> template < class Monoid > struct ReRooting { using size_type = std::size_t; using edge_type = std::tuple< size_type, size_type, size_type >; using graph_type = std::vector< std::vector< edge_type > >; using T = typename Monoid::T; using dig_f_type = std::function< T(T, size_type edge_id, size_type from, size_type to) >; using after_f_type = std::function< T(T, size_type vertex_id, size_type degree_of_this) >; using vector_bool_type = std::vector< int >; graph_type graph; size_type n; std::vector< size_type > start; std::vector< T > dp; vector_bool_type did; std::vector< T > L; std::vector< T > R; dig_f_type dig; after_f_type after; static T default_dig(const T &a, ...) { return a; } static T default_after(const T &a, ...) { return a; } bool built; ReRooting() : n(0) {} ReRooting(size_type n, dig_f_type dig = default_dig, after_f_type after = default_after) : dig(dig), after(after) { clear(n); } ReRooting(std::vector< std::vector< int > > graph, dig_f_type dig = default_dig, after_f_type after = default_after) : ReRooting(graph.size(), dig, after) { for(size_type from = 0; from < n; from++) { for(auto to : graph[from]) if(static_cast< size_type >(to) < from) { add_edge(from, to); } } } void clear() { clear(n); } void clear(size_type n) { this->n = n; graph.resize(n); graph.assign(n, std::vector< edge_type >()); dp.resize(3 * n); did.resize(3 * n); did.assign(3 * n, 0); L.resize(3 * n); R.resize(3 * n); start.resize(n); added = 0; built = 0; } size_type added = 0; void add_edge(size_type a, size_type b, size_type id = static_cast< size_type >(-1)) { assert(!built); assert(a < n && b < n && a != b); if(id == static_cast< size_type >(-1)) id = added; graph[a].emplace_back(b, graph[b].size(), id); graph[b].emplace_back(a, graph[a].size() - 1, id); added++; } void set_dig(dig_f_type dig = default_dig) { assert(!built); this->dig = dig; } void set_after(after_f_type after = default_after) { assert(!built); this->after = after; } void build() { assert(!built); built = 1; if(n == 0) return; assert(added == n - 1); for(size_type i = 0; i + 1 < n; i++) { start[i + 1] = start[i] + graph[i].size() + 1; } dfs_first(0, graph[0].size()); } public: T dfs(size_type i) { return dfs(i, graph[i].size()); } T dfs_from(size_type i, size_type j) { assert(built); assert(j < n); // TODO : どうする? // return dfs(i, , 0); } private: T proceed_root(size_type i) { for(size_type x = 0; x < graph[i].size(); x++) { auto to = graph[i][x]; size_type j, rev, edge_id; std::tie(j, rev, edge_id) = to; R[start[i] + x] = L[start[i] + x] = dig(dp[start[j] + rev], edge_id, i, j); } for(int x = 1; x < static_cast< int >(graph[i].size()); x++) L[start[i] + x] = Monoid::op(L[start[i] + x - 1], L[start[i] + x]); for(int x = static_cast< int >(graph[i].size()) - 2; x >= 0; x--) R[start[i] + x] = Monoid::op(R[start[i] + x], R[start[i] + x + 1]); return L[start[i] + graph[i].size() - 1]; } void dfs_first(size_type i0, size_type p0) { std::vector< std::tuple< size_type, size_type, bool > > stk; stk.reserve(n); stk.emplace_back(i0, p0, 0); while(stk.size()) { size_type i, p; bool up; std::tie(i, p, up) = stk.back(); stk.pop_back(); int deg = graph[i].size() - (p != graph[i].size() ? 1 : 0); if(up) { did[start[i] + p] = 1; T res = Monoid::identity(); if(p == graph[i].size()) { // O(deg) res = proceed_root(i); } else { // O(deg) for(size_type x = 0; x < graph[i].size(); x++) if(x != p) { size_type j, rev, edge_id; std::tie(j, rev, edge_id) = graph[i][x]; res = Monoid::op(res, dig(dp[start[j] + rev], edge_id, i, j)); } } dp[start[i] + p] = after(res, i, deg); } else { stk.emplace_back(i, p, 1); for(size_type x = 0; x < graph[i].size(); x++) if(x != p) { size_type j, rev, edge_id; std::tie(j, rev, edge_id) = graph[i][x]; stk.emplace_back(j, rev, 0); } } } } T dfs(size_type i0, size_type p0) { assert(built); assert(i0 < n); assert(p0 <= graph[i0].size()); if(did[start[i0] + p0]) return dp[start[i0] + p0]; std::vector< std::tuple< size_type, size_type, bool > > stk; stk.reserve(n); stk.emplace_back(i0, p0, 0); while(stk.size()) { size_type i, p; bool up; std::tie(i, p, up) = stk.back(); stk.pop_back(); if(up) { int deg = graph[i].size() - (p != graph[i].size() ? 1 : 0); did[start[i] + p] = 1; T res = Monoid::identity(); if(p == graph[i].size()) { // O(deg) res = proceed_root(i); } else { // O(1) res = Monoid::op( p >= 1 ? L[start[i] + p - 1] : Monoid::identity(), p + 1 < graph[i].size() ? R[start[i] + p + 1] : Monoid::identity()); } dp[start[i] + p] = after(res, i, deg); } else { stk.emplace_back(i, p, 1); if(p == graph[i].size()) { for(size_type x = 0; x < graph[i].size(); x++) { size_type j, rev, edge_id; std::tie(j, rev, edge_id) = graph[i][x]; if(!did[start[j] + rev]) stk.emplace_back(j, rev, 0); } } else { if(!did[start[i] + graph[i].size()]) { stk.emplace_back(i, graph[i].size(), 0); } } } } return dp[start[i0] + p0]; } }; /// }}}--- //// // my monoid, m-act {{{ struct MyMonoid { using T = int; static T op(const T &a, const T &b) { return a && b; } static T identity() { return 1; } }; // }}} using rerooting = ReRooting< MyMonoid >; using T = rerooting::T; T dig(T a, int id, int from, int to) { return !a; } T after(T a, int i, int deg) { return a; } int n; int main() { std::ios::sync_with_stdio(false), std::cin.tie(0); cin >> n; rerooting rr(n, dig, after); for(int i = 0; i < n - 1; i++) { int a, b; cin >> a >> b; a--; b--; rr.add_edge(a, b); } rr.build(); vector< int > v; for(int i = 0; i < n; i++) if(rr.dfs(i)) v.emplace_back(i); cout << v.size() << "\n"; for(int e : v) cout << e + 1 << "\n"; return 0; }