Submission #380613

#TimeUsernameProblemLanguageResultExecution timeMemory
380613KoDSimurgh (IOI17_simurgh)C++17
0 / 100
1 ms364 KiB
#include <bits/stdc++.h> #include "simurgh.h" template <class T> using Vec = std::vector<T>; template <class F> struct RecLambda: private F { explicit RecLambda(F &&f): F(std::forward<F>(f)) { } template <class... Args> decltype(auto) operator () (Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); } }; struct DSU { Vec<int> par; DSU(const int n): par(n, -1) { } int find(const int u) { return par[u] < 0 ? u : par[u] = find(par[u]); } bool merge(int x, int y) { x = find(x); y = find(y); if (x == y) return false; if (par[x] > par[y]) std::swap(x, y); par[x] += par[y]; par[y] = x; return true; } }; Vec<int> find_roads(int n, Vec<int> u, Vec<int> v) { const int m = (int) u.size(); Vec<Vec<int>> graph(n); std::map<std::pair<int, int>, int> edge; for (int i = 0; i < m; ++i) { graph[u[i]].push_back(v[i]); graph[v[i]].push_back(u[i]); edge[{ u[i], v[i] }] = i; edge[{ v[i], u[i] }] = i; } std::set<int> tree; Vec<int> back; Vec<int> parent(n), depth(n, -1); RecLambda([&](auto dfs, const int u, const int p, const int d) -> void { parent[u] = p; depth[u] = d; for (const auto v: graph[u]) { if (v != p) { if (depth[v] == -1) { tree.insert(edge[{ u, v }]); dfs(v, u, d + 1); } else { if (depth[v] < depth[u]) { back.push_back(edge[{ u, v }]); } } } } })(0, -1, 0); const auto base = count_common_roads(Vec<int>(tree.begin(), tree.end())); const auto exchange = [&](const int e, const int f) { tree.erase(e); tree.insert(f); const auto ret = count_common_roads(Vec<int>(tree.begin(), tree.end())); tree.erase(f); tree.insert(e); return ret; }; Vec<int> state(m); for (const auto e: back) { int a = u[e], b = v[e]; if (depth[a] < depth[b]) { std::swap(a, b); } Vec<int> done, same, differ; while (a != b) { const auto p = parent[a]; const auto f = edge[{ a, b }]; if (state[f] == 0) { const auto tmp = exchange(e, f); if (exchange(e, f) == base) { same.push_back(f); } else { state[e] = (tmp > base ? 1 : -1); differ.push_back(f); } } else { done.push_back(f); } a = p; } if (state[e] == 0 && same.size() + differ.size() > 0) { if (done.empty()) { state[e] = -1; } else { const auto f = done.front(); const auto tmp = exchange(e, f); if (tmp == base) { state[e] = state[f]; } else { state[e] = -state[f]; } } } for (const auto f: same) { state[f] = state[e]; } for (const auto f: differ) { state[f] = -state[e]; } } for (const auto e: tree) { if (state[e] == 0) { state[e] = 1; } } const auto count = [&](const Vec<int> &es) { Vec<int> ask; ask.reserve(n - 1); DSU dsu(n); for (const auto e: es) { ask.push_back(e); dsu.merge(u[e], v[e]); } int sum = 0; for (const auto e: tree) { if (dsu.merge(u[e], v[e])) { ask.push_back(e); sum += (state[e] == 1); } } return count_common_roads(ask) - sum; }; for (int i = 0; i < n; ++i) { std::set<int> remain; for (const auto j: graph[i]) { const auto e = edge[{ i, j }]; if (state[e] == 0) { remain.insert(e); } } while (true) { Vec<int> vec(remain.begin(), remain.end()); if (count(vec) == 0) { break; } while (vec.size() > 1) { const auto m = (int) vec.size() / 2; Vec<int> left(vec.begin(), vec.begin() + m); Vec<int> right(vec.begin() + m, vec.end()); if (count(left) > 0) { vec = std::move(left); } else { vec = std::move(right); } } state[vec[0]] = 1; remain.erase(vec[0]); } for (const auto e: remain) { state[e] = -1; } } Vec<int> ret; for (int i = 0; i < m; ++i) { if (state[i] == 1) { ret.push_back(i); } } return ret; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...