Submission #563849

#TimeUsernameProblemLanguageResultExecution timeMemory
563849piOOEPipes (CEOI15_pipes)C++17
100 / 100
2247 ms9116 KiB
#include <bits/stdc++.h> using namespace std; #define all(x) begin(x), end(x) #define sz(x) ((int)size(x)) #define trace(x) cout << #x << ": " << (x) << endl; typedef long long ll; const int N = 100000, M = 6000000; int p[2][N]; int get(int a, int i) { return (p[i][a] != a ? p[i][a] = get(p[i][a], i) : a); } bool same(int a, int b, int i) { return get(a, i) == get(b, i); } bool mrg(int a, int b, int i) { a = get(a, i), b = get(b, i); if (a == b) return false; p[i][b] = a; return true; } vector<pair<int, int>> g[N]; //binary jumps with O(n) memory //https://peltorator.ru/posts/linear_binups/ int jump[N], parent[N], depth[N], id_p[N]; int lca(int a, int b) { if (depth[a] < depth[b]) swap(a, b); while (depth[a] > depth[b]) { if (depth[jump[a]] >= depth[b]) { a = jump[a]; } else { a = parent[a]; } } while (a != b) { if (jump[a] != jump[b]) { a = jump[a]; b = jump[b]; } else { a = parent[a]; b = parent[b]; } } return a; } void add_leaf(int v, int par) { assert(par != -1 && par != v); parent[v] = par; depth[v] = depth[par] + 1; if (depth[par] - depth[jump[par]] == depth[jump[par]] - depth[jump[jump[par]]]) { jump[v] = jump[jump[par]]; } else { jump[v] = par; } } int sz[N]; bool usedE[N]; //used edges //d1 is just our tree, d2 is for merging in a path void dfs(int v, int par, int id) { add_leaf(v, par); p[1][v] = v; id_p[v] = id; for (auto [to, i]: g[v]) { if (to != par) { dfs(to, v, i); } } } void union_path(int a, int b) { int c = lca(a, b); while (depth[a = get(a, 1)] > depth[c]) { usedE[id_p[a]] = true; mrg(parent[a], a, 1); } while (depth[b = get(b, 1)] > depth[c]) { usedE[id_p[b]] = true; mrg(parent[b], b, 1); } } void merge(int a, int b, int idx) { int pa = get(a, 0); int pb = get(b, 0); if (sz[pa] < sz[pb]) { swap(a, b); swap(pa, pb); } g[a].emplace_back(b, idx); g[b].emplace_back(a, idx); dfs(b, a, idx); mrg(pa, pb, 0); sz[pa] += sz[pb]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); iota(jump, jump + N, 0); iota(parent, parent + N, 0); iota(p[0], p[0] + N, 0); iota(p[1], p[1] + N, 0); fill(sz, sz + N, 1); int n, m; cin >> n >> m; int idx = 0; for (int i = 0; i < m; ++i) { int a, b; cin >> a >> b; --a, --b; if (same(a, b, 0)) { union_path(a, b); } else { merge(a, b, idx); ++idx; } } for (int i = 0; i < n; ++i) { for (auto [to, j] : g[i]) { if (!usedE[j]) { cout << i + 1 << " " << to + 1 << "\n"; usedE[j] = true; } } } return 0; }
#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...
#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...