Submission #94564

#TimeUsernameProblemLanguageResultExecution timeMemory
94564wxh010910Simurgh (IOI17_simurgh)C++17
100 / 100
793 ms9720 KiB
#include <bits/stdc++.h> #include "simurgh.h" using namespace std; class dsu { public: vector<int> p; int n; dsu(int n): n(n) { p.resize(n); for (int i = 0; i < n; ++i) { p[i] = i; } } inline int find(int x) { while (x != p[x]) { x = p[x] = p[p[x]]; } return x; } inline bool unite(int x, int y) { x = find(x); y = find(y); if (x == y) { return false; } else { p[x] = y; return true; } } }; vector<int> find_roads(int n, vector<int> u, vector<int> v) { int m = u.size(); vector<int> color(m, -1); vector<int> tree; vector<int> ans; set<int> cur; auto query = [&](vector<int> edges) { dsu d(n); for (auto i : edges) { d.unite(u[i], v[i]); } int more = 0; for (auto i : tree) { if (d.unite(u[i], v[i])) { edges.push_back(i); more += color[i]; } } return count_common_roads(edges) - more; }; vector<vector<pair<int, int>>> adj(n); dsu d(n); for (int i = 0; i < m; ++i) { if (d.unite(u[i], v[i])) { adj[u[i]].emplace_back(v[i], i); adj[v[i]].emplace_back(u[i], i); tree.push_back(i); } else { cur.insert(i); } } vector<int> pv(n, -1); vector<int> pe(n, -1); vector<int> depth(n); function<void(int)> dfs = [&](int x) { for (auto p : adj[x]) { if (p.first != pv[x]) { pv[p.first] = x; pe[p.first] = p.second; depth[p.first] = depth[x] + 1; dfs(p.first); } } }; dfs(0); auto get_path = [&](int x, int y) { vector<int> res; while (x != y) { if (depth[x] >= depth[y]) { res.push_back(pe[x]); x = pv[x]; } else { res.push_back(pe[y]); y = pv[y]; } } return res; }; for (int i = 0; i < m; ++i) { vector<int> path = get_path(u[i], v[i]); if (path.size() == 1) { continue; } bool all_colored = true; for (auto j : path) { if (color[j] == -1) { all_colored = false; break; } } if (all_colored) { continue; } path.push_back(i); int max_common_edges = -n; for (auto j : path) { if (color[j] != -1) { vector<int> edges; for (auto k : path) { if (k != j) { edges.push_back(k); } } max_common_edges = query(edges) + color[j]; break; } } vector<pair<int, int>> all; for (auto j : path) { if (color[j] == -1) { vector<int> edges; for (auto k : path) { if (k != j) { edges.push_back(k); } } int res = query(edges); max_common_edges = max(max_common_edges, res); all.emplace_back(j, res); } } for (auto p : all) { color[p.first] = p.second < max_common_edges; } } for (auto i : tree) { if (color[i] == -1) { color[i] = 1; } if (color[i]) { ans.push_back(i); } } function<void(vector<int>, int)> solve = [&](vector<int> e, int common) { int n = e.size(); if (!common) { return; } else if (common == n) { for (auto i : e) { ans.push_back(i); } } else { vector<int> left(e.begin(), e.begin() + (n >> 1)); vector<int> right(e.begin() + (n >> 1), e.end()); int common_left = query(left); int common_right = common - common_left; solve(left, common_left); solve(right, common_right); } }; for (int i = 0; i < n; ++i) { vector<int> useful; for (auto j : cur) { if (u[j] == i || v[j] == i) { useful.push_back(j); } } if (!useful.empty()) { for (auto j : useful) { cur.erase(j); } solve(useful, query(useful)); } } sort(ans.begin(), ans.end()); return ans; }
#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...