結果
問題 | No.1817 Reversed Edges |
ユーザー |
![]() |
提出日時 | 2022-01-21 22:08:40 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 119 ms / 2,000 ms |
コード長 | 5,932 bytes |
コンパイル時間 | 1,459 ms |
コンパイル使用メモリ | 133,320 KB |
最終ジャッジ日時 | 2025-01-27 13:53:13 |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 23 |
ソースコード
// ===== template.hpp =====#include <algorithm>#include <array>#include <bitset>#include <cassert>#include <cmath>#include <iomanip>#include <iostream>#include <map>#include <numeric>#include <queue>#include <set>#include <stack>#include <string>#include <tuple>#include <unordered_map>#include <unordered_set>#include <utility>#include <vector>#define OVERRIDE(a, b, c, d, ...) d#define REP2(i, n) for (i32 i = 0; i < (n); ++i)#define REP3(i, m, n) for (i32 i = (m); i < (n); ++i)#define REP(...) OVERRIDE(__VA_ARGS__, REP3, REP2)(__VA_ARGS__)#define PER(i, n) for (i32 i = (n) - 1; i >= 0; --i)#define ALL(x) begin(x), end(x)using namespace std;using u32 = unsigned int;using u64 = unsigned long long;using u128 = __uint128_t;using i32 = signed int;using i64 = signed long long;using i128 = __int128_t;template <typename T>using Vec = vector<T>;template <typename T>bool chmin(T &x, const T &y) {if (x > y) {x = y;return true;}return false;}template <typename T>bool chmax(T &x, const T &y) {if (x < y) {x = y;return true;}return false;}[[maybe_unused]] constexpr i32 inf = 1000000100;[[maybe_unused]] constexpr i64 inf64 = 3000000000000000100;struct SetIO {SetIO() {ios::sync_with_stdio(false);cin.tie(nullptr);cout << fixed << setprecision(10);}} set_io;// ===== template.hpp =====#ifdef DEBUGF#include "../new_library/other/debug.hpp"#else#define DBG(x) (void) 0#endif// ===== rerooting.hpp =====#ifndef REROOTING_HPP#define REROOTING_HPP#include <optional>#include <queue>#include <utility>#include <vector>template <typename G, typename T, typename Apply, typename Merge>T rerooting_sub1(const G &g,const T &id,const Apply &ap,const Merge &me,std::size_t v,std::size_t p,std::vector<std::vector<std::optional<T>>> &dp) {T acc = id;for (std::size_t i = 0; i < g[v].size(); ++i) {if ((std::size_t)g[v][i] != p) {T val = rerooting_sub1(g, id, ap, me, (std::size_t)g[v][i], v, dp);dp[v][i] = ap(val, v, g[v][i]);acc = me(acc, *dp[v][i]);}}return acc;}template <typename G, typename T, typename Apply, typename Merge>void rerooting_sub2(const G &g,const T &id,const Apply &ap,const Merge &me,std::size_t root,std::vector<std::vector<std::optional<T>>> &dp) {std::queue<std::pair<std::size_t, T>> que;que.emplace(root, id);while (!que.empty()) {auto [v, val] = que.front();que.pop();std::vector<T> acc_l(g[v].size() + 1);acc_l[0] = id;std::size_t emp_idx = -1;for (std::size_t i = 0; i < g[v].size(); ++i) {if (!(bool)dp[v][i]) {dp[v][i] = ap(val, v, g[v][i]);emp_idx = i;}acc_l[i + 1] = me(acc_l[i], *dp[v][i]);}T acc_r = id;for (std::size_t i = g[v].size() - 1; i < g[v].size(); --i) {if (i != emp_idx) {que.emplace((std::size_t)g[v][i], me(acc_l[i], acc_r));}acc_r = me(*dp[v][i], acc_r);}}}// Apply: Fn(T, size_t, E) -> T// Merge: Fn(T, T) -> Ttemplate <typename G, typename T, typename Apply, typename Merge>std::vector<T>rerooting(const G &g, const T &id, const Apply &ap, const Merge &me) {std::vector<std::vector<std::optional<T>>> dp(g.size());for (std::size_t i = 0; i < g.size(); ++i) {dp[i].resize(g[i].size(), std::nullopt);}rerooting_sub1(g, id, ap, me, 0, 0, dp);rerooting_sub2(g, id, ap, me, 0, dp);std::vector<T> buf(g.size(), id);for (std::size_t i = 0; i < g.size(); ++i) {for (std::optional<T> &val : dp[i]) {buf[i] = me(buf[i], std::move(*val));}}return buf;}#endif// ===== rerooting.hpp =====// ===== graph.hpp =====#ifndef GRAPH_HPP#define GRAPH_HPP#include <utility>#include <vector>template <typename Edge>class Graph {std::vector<std::vector<Edge>> edges;public:Graph() : edges() {}Graph(std::size_t v) : edges(v) {}template <typename... T>void add_edge(std::size_t from, std::size_t to, T &&...val) {edges[from].emplace_back(Edge(to, std::forward<T>(val)...));}template <typename... T>void add_undirected_edge(std::size_t u, std::size_t v, const T &...val) {edges[u].emplace_back(Edge(v, val...));edges[v].emplace_back(Edge(u, val...));}std::size_t size() const {return edges.size();}const std::vector<Edge> &operator[](std::size_t v) const {return edges[v];}std::vector<Edge> &operator[](std::size_t v) {return edges[v];}};struct UnweightedEdge {std::size_t to;UnweightedEdge(std::size_t t) : to(t) {}operator std::size_t() const {return to;}using Weight = std::size_t;Weight wt() const {return 1;}};template <typename T>struct WeightedEdge {std::size_t to;T wt;WeightedEdge(std::size_t t, const T &w) : to(t), wt(w) {}operator std::size_t() const {return to;}using Weight = T;Weight weight() const {return wt;}};#endif// ===== graph.hpp =====int main() {i32 n;cin >> n;Graph<i32> g(n);REP(i, n - 1) {i32 a, b;cin >> a >> b;--a;--b;g.add_undirected_edge(a, b);}const auto ap = [](i32 s, i32 v, i32 e) -> i32 {if (e < v) {return s + 1;} else {return s;}};const auto me = [](i32 s1, i32 s2) -> i32 {return s1 + s2;};Vec<i32> dp = rerooting(g, 0, ap, me);REP(i, n) {cout << dp[i] << '\n';}}