제출 #563810

#제출 시각아이디문제언어결과실행 시간메모리
563810piOOEPipes (CEOI15_pipes)C++17
40 / 100
2200 ms65536 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; struct dsu { int p[N], sz[N]; dsu() = default; dsu(int n) { iota(p, p + n, 0); fill(sz, sz + n, 1); } void init(int n) { iota(p, p + n, 0); fill(sz, sz + n, 1); } int get(int a) { int x = a; while (p[a] != a) { a = p[a]; } while (x != a) { int v = p[x]; p[x] = a; x = v; } return a; } bool same(int a, int b) { return get(a) == get(b); } bool mrg(int a, int b) { a = get(a), b = get(b); if (a == b) return false; p[b] = a; sz[a] += sz[b]; 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 A[N], B[N]; bool usedE[N]; //used edges dsu d1, d2; //d1 is just ouor tree, d2 is for merging in a path void dfs(int v, int par, int id) { add_leaf(v, par); d2.p[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 = d2.get(a)] > depth[c]) { usedE[id_p[a]] = true; d2.mrg(parent[a], a); } while (depth[b = d2.get(b)] > depth[c]) { usedE[id_p[b]] = true; d2.mrg(parent[b], b); } } void merge(int a, int b, int idx) { int pa = d1.get(a); int pb = d1.get(b); if (d1.sz[pa] < d1.sz[pb]) swap(a, b); g[a].emplace_back(b, idx); g[b].emplace_back(a, idx); dfs(b, a, idx); d1.mrg(a, b); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); iota(jump, jump + N, 0); iota(parent, parent + N, 0); int n, m; cin >> n >> m; d1.init(n); d2.init(n); int idx = 0; for (int i = 0; i < m; ++i) { int a, b; cin >> a >> b; --a, --b; if (d1.same(a, b)) { union_path(a, b); } else { A[idx] = a, B[idx] = b; merge(a, b, idx); ++idx; } } for (int i = 0; i < idx; ++i) { if (!usedE[i]) { cout << A[i] + 1 << " " << B[i] + 1 << '\n'; } } 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...