Submission #1195701

#TimeUsernameProblemLanguageResultExecution timeMemory
1195701steveonalexSimurgh (IOI17_simurgh)C++20
0 / 100
0 ms328 KiB
#include "simurgh.h" #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MASK(i) (1ULL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll gcd(ll a, ll b){return __gcd(abs(a), abs(b));} ll lcm(ll a, ll b){return abs(a) / gcd(a, b) * abs(b);} ll LASTBIT(ll mask){return (mask) & (-mask);} int pop_cnt(ull mask){return __builtin_popcountll(mask);} int ctz(ull mask){return __builtin_ctzll(mask);} int logOf(ull mask){return 63 - __builtin_clzll(mask);} // mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T container, string separator = " ", string finish = "\n", ostream &out = cout){ for(auto item: container) out << item << separator; out << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } namespace Sub{ struct DSU{ int n; vector<int> parent, sz; DSU(int _n){ n = _n; parent.resize(n); sz.resize(n, 1); for(int i = 0; i<n; ++i) parent[i] = i; } int find_set(int u){return (u == parent[u]) ? u : (parent[u] = find_set(parent[u]));} bool same_set(int u, int v){return find_set(u) == find_set(v);} bool join_set(int u, int v){ u = find_set(u), v = find_set(v); if (u != v){ if (sz[u] < sz[v]) swap(u, v); parent[v] = u; sz[u] += sz[v]; return true; } return false; } int get_size(int u){return sz[find_set(u)];} }; const int N = 505; vector<pair<int, int>> graph[N]; pair<int, int> parent[N]; int h[N]; void reset(int n){ for(int i = 0; i < n; ++i) { graph[i].clear(); h[i] = 0; parent[i] = make_pair(0, 0); } } void dfs(int u, int p){ if (u == p) h[u] = 1; else h[u] = h[p] + 1; for(pair<int, int> v: graph[u]) if (v.first != p){ parent[v.first] = make_pair(u, v.second); dfs(v.first, u); } } vector<int> solve(int n, vector<int> U, vector<int> V){ int m = U.size(); reset(n); vector<int> spanning_tree; DSU mst(n); for(int i = 0; i < m; ++i){ if (mst.join_set(U[i], V[i])){ graph[U[i]].push_back(make_pair(V[i], i)); graph[V[i]].push_back(make_pair(U[i], i)); spanning_tree.push_back(i); } } int og_cnt = count_common_roads(spanning_tree); dfs(0, 0); vector<int> cost(m, -1); vector<int> of_spanning_tree(m); for(int i: spanning_tree){ of_spanning_tree[i] = true; } for(int i = 0; i < m; ++i) if (!of_spanning_tree[i]){ vector<int> known_edges, unknown_edges; int u = U[i], v = V[i]; while(u != v){ if (h[u] < h[v]) swap(u, v); int e = parent[u].second; if (cost[e] == -1) unknown_edges.push_back(e); else known_edges.push_back(e); u = parent[u].first; } if (unknown_edges.empty()) continue; if (known_edges.size()){ int j = known_edges.back(); DSU mst(n); vector<int> cur_spanning_tree; cur_spanning_tree.push_back(i); mst.join_set(U[j], V[j]); for(int k: spanning_tree) if (k != j){ if (mst.join_set(U[k], V[k])) cur_spanning_tree.push_back(k); } int cur_cnt = count_common_roads(cur_spanning_tree); cost[i] = cost[j] + cur_cnt - og_cnt; for(int j: unknown_edges){ DSU mst(n); vector<int> cur_spanning_tree; cur_spanning_tree.push_back(i); mst.join_set(U[j], V[j]); for(int k: spanning_tree) if (k != j){ if (mst.join_set(U[k], V[k])) cur_spanning_tree.push_back(k); } int cur_cnt = count_common_roads(cur_spanning_tree); cost[j] = cost[i] - cur_cnt + og_cnt; } } else{ // covering no edge wtf vector<int> diff; for(int j: unknown_edges){ DSU mst(n); vector<int> cur_spanning_tree; cur_spanning_tree.push_back(i); mst.join_set(U[j], V[j]); for(int k: spanning_tree) if (k != j){ if (mst.join_set(U[k], V[k])) cur_spanning_tree.push_back(k); } int cur_cnt = count_common_roads(cur_spanning_tree); diff.push_back(cur_cnt - og_cnt); } pair<int,int> range = make_pair(1, -1); for(int i: diff){ minimize(range.first, i); maximize(range.second, i); } if (range == make_pair(0, 0)){ cost[i] = 0; for(int j: unknown_edges) cost[j] = 0; } else if (range.second == 1){ cost[i] = 1; for(int j = 0; j < (int) unknown_edges.size(); ++j) cost[unknown_edges[j]] = 1 - diff[j]; } else{ cost[i] = 0; for(int j = 0; j < (int) unknown_edges.size(); ++j) cost[unknown_edges[j]] = -diff[j]; } } } for(int i = 0; i < m; ++i) if (cost[i] == -1 && of_spanning_tree[i]) // bridge cost[i] = 1; while(true){ DSU mst(n); vector<int> pending; for(int i = 0; i < m; ++i) if (cost[i] == -1){ if (mst.join_set(U[i], V[i])){ pending.push_back(i); } } if (pending.empty()) break; vector<int> cur_spanning_tree = pending; int cur_cost = 0; for(int i: spanning_tree) { if (mst.join_set(U[i], V[i])){ cur_spanning_tree.push_back(i); cur_cost -= cost[i]; } } cur_cost += count_common_roads(cur_spanning_tree); int last = -1; for(int i: pending) cost[i] = 0; for(int it = 1; it <= cur_cost; ++it){ int l = last + 1, r = pending.size() - (cur_cost - it) - 1; while(l < r){ int mid = (l + r) >> 1; vector<int> cur_spanning_tree; for(int i = 0; i <= mid; ++i) { cur_spanning_tree.push_back(pending[i]); } int cur_cost = 0; for(int i: spanning_tree) { if (mst.join_set(U[i], V[i])){ cur_spanning_tree.push_back(i); cur_cost -= cost[i]; } } cur_cost += count_common_roads(cur_spanning_tree); if (cur_cost >= it) r = mid; else l = mid + 1; } cost[pending[l]] = 1; last = l; } } vector<int> ans; for(int i = 0; i < m; ++i) if (cost[i]) ans.push_back(i); if (ans.size() != n-1) assert(false); if (count_common_roads(ans) != n-1) assert(false); return ans; } } vector<int> find_roads(int n, vector<int> u, vector<int> v){ return Sub::solve(n, u, v); } // int main(void){ // ios::sync_with_stdio(0);cin.tie(0); cout.tie(0); // clock_t start = clock(); // cerr << "Time elapsed: " << clock() - start << " ms!\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...