Submission #143967

#TimeUsernameProblemLanguageResultExecution timeMemory
143967VladaMG98Split the Attractions (IOI19_split)C++17
18 / 100
160 ms19720 KiB
#include <bits/stdc++.h> #include "split.h" using namespace std; const int MAXN = 100010; int subtree_size[MAXN]; vector<int> adj[MAXN]; int parent[MAXN]; void dfs(int src = 0, int prev = -1) { //printf("dfs %d %d\n", src, prev); subtree_size[src] = 1; parent[src] = prev; for(auto &xt : adj[src]) { if(xt - prev) { dfs(xt, src); subtree_size[src] += subtree_size[xt]; } } } vector<int> get_solution(vector<int> v1, int n1, vector<int> v2, int n2, int n) { vector<int> ans(n, 6 - n1 - n2); for(auto &x : v1) { ans[x] = n1; } for(auto &x : v2) { ans[x] = n2; } return ans; } bool marked[MAXN]; vector<int> extract(int src, int wrong, int sz) { marked[wrong] = true; vector<int> ans; stack<int> nodes; nodes.push(src); marked[src] = true; while((int)ans.size() < sz) { int node = nodes.top(); nodes.pop(); ans.push_back(node); for(auto &x : adj[node]) { if(!marked[x]) { marked[x] = true; nodes.push(x); } } } for(auto &x : ans) { marked[x] = false; } marked[wrong] = false; return ans; } vector<int> blank(int n) { vector<int> ans(n, 0); return ans; } int dsu[MAXN]; void init_set(int x) { dsu[x] = x; } int get(int x) { if(dsu[x] == x) return x; return dsu[x] = get(dsu[x]); } bool unite(int x, int y) { int xr = get(x), yr = get(y); if(xr == yr) return false; if(rand() % 2) swap(xr, yr); dsu[xr] = yr; return true; } void create_spanning_tree(int n, vector<int> &st_p, vector<int> &st_q, vector<int> p, vector<int> q) { for(int i = 0; i < n; i++) { init_set(i); } int m = (int)p.size(); for(int i = 0; i < m; i++) { if(unite(p[i], q[i])) { st_p.push_back(p[i]); st_q.push_back(q[i]); } } assert((int)st_p.size() == n - 1); } int belongs[MAXN]; set<int> comp_adj[MAXN]; int cnt_nodes[MAXN]; int comp_size; vector<int> comp_comp; bool comp_mark[MAXN]; void dfs2(int src) { comp_size += cnt_nodes[src]; comp_mark[src] = true; comp_comp.push_back(src); for(auto &xt : comp_adj[src]) { if(!comp_mark[xt]) { dfs2(xt); } } } vector<int> find_split(int n, int a, int b, int c, vector<int> p, vector<int> q) { pair<int, int> arr[] = {{a, 1}, {b, 2}, {c, 3}}; sort(arr, arr + 3); int A = arr[0].first, B = arr[1].first, C = arr[2].first; vector<int> st_p, st_q; create_spanning_tree(n, st_p, st_q, p, q); int m = (int)p.size(); for(int i = 0; i < n - 1; i++) { adj[st_p[i]].push_back(st_q[i]); adj[st_q[i]].push_back(st_p[i]); } dfs(); //for(int i = 0; i < n; i++) { // printf("subtree_size[%d] = %d\n", i, subtree_size[i]); //} for(int i = 0; i < m; i++) { int u = p[i], v = q[i]; if(subtree_size[u] > subtree_size[v]) swap(u, v); int under = subtree_size[u]; int rest = n - under; if(under >= A && rest >= A) { //printf("found for edge %d - %d\n", u, v); //we've got a solution vector<int> set_A, set_B; if(under < rest) { set_A = extract(u, v, A); set_B = extract(v, u, B); } else { set_A = extract(v, u, A); set_B = extract(u, v, B); } return get_solution(set_A, arr[0].second, set_B, arr[1].second, n); } } //there is no edge connecting two subtrees of sizes >= a //meaning that it's a star with all subtrees attached of size < a //in tree, there is no such solution for(int node = 0; node < n; node++) { vector<pair<int, int>> sizes; int sm = 0; for(auto &xt : adj[node]) { if(xt != parent[node]) { sizes.push_back({subtree_size[xt], xt}); sm += subtree_size[xt]; } } if(node) { sizes.push_back({n - 1 - sm, parent[node]}); } int mx = 0; for(auto &pr : sizes) { mx = max(mx, pr.first); } if(mx < A) { printf("I am deciding on node %d\n", node); for(int i = 0; i < (int)sizes.size(); i++) { vector<int> comp_here = extract(sizes[i].second, node, sizes[i].first); for(auto &x : comp_here) { belongs[x] = i + 1; marked[x] = false; } marked[node] = false; cnt_nodes[i + 1] = sizes[i].first; } int new_nodes = (int)sizes.size(); for(int i = 0; i < m; i++) { if(p[i] != node && q[i] != node) { comp_adj[belongs[p[i]]].insert(belongs[q[i]]); comp_adj[belongs[q[i]]].insert(belongs[p[i]]); } } for(int i = 1; i <= new_nodes; i++) { if(marked[i]) continue; comp_size = 0; comp_comp.clear(); dfs2(i); for(auto &x : comp_comp) { comp_mark[x] = false; } if(comp_size >= A) { //we have a solution int start_node = sizes[i - 1].second; vector<int> ans_A = extract(start_node, node, A); for(auto &x : ans_A) { marked[x] = true; } vector<int> ans_B = extract(node, MAXN - 1, B); return get_solution(ans_A, arr[0].second, ans_B, arr[1].second, n); } else { return blank(n); } } } } assert(false); return blank(n); }

Compilation message (stderr)

split.cpp: In function 'std::vector<int> find_split(int, int, int, int, std::vector<int>, std::vector<int>)':
split.cpp:117:45: warning: unused variable 'C' [-Wunused-variable]
     int A = arr[0].first, B = arr[1].first, C = arr[2].first;
                                             ^
#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...