Submission #385664

#TimeUsernameProblemLanguageResultExecution timeMemory
385664jhnah917Split the Attractions (IOI19_split)C++14
100 / 100
270 ms24228 KiB
/****************************** Author: jhnah917(Justice_Hui) g++ -std=c++17 -DLOCAL ******************************/ #ifndef LOCAL #include "split.h" #endif #include <bits/stdc++.h> #define x first #define y second #define all(v) v.begin(), v.end() #define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end()) #define IDX(v, x) (lower_bound(all(v), x) - v.begin()) using namespace std; using uint = unsigned; using ll = long long; using ull = unsigned long long; using PII = pair<int, int>; constexpr int SZ = 101010; template<size_t _Sz> struct UnionFind { int P[_Sz], W[_Sz]; UnionFind(){ clear(); } void clear(){ iota(P, P+_Sz, 0); fill(W, W+_Sz, 1); } int find(int v){ return v == P[v] ? v : P[v] = find(P[v]); } bool merge(int u, int v){ u = find(u); v = find(v); if(u == v) return false; P[u] = v; W[v] += W[u]; return true; } }; int N, M, A, B, C, S[SZ], chk[SZ]; PII ORD[3]; vector<int> G[SZ], Tree[SZ], Comp[SZ]; UnionFind<SZ> UF; int get_sz(int v, int b=-1){ S[v] = 1; for(auto i : Tree[v]) if(i != b) S[v] += get_sz(i, v); return S[v]; } int get_cent(int v, int tot, int b=-1){ for(auto i : Tree[v]) if(i != b && S[i]*2 > tot) return get_cent(i, tot, v); return v; } vector<int> dfs_subtree(int v, int b){ vector<int> ret; function<void(int,int)> go = [&go,&ret](int v, int b){ ret.push_back(v); for(auto i : Tree[v]) if(i != b) go(i, v); }; go(v, b); return move(ret); } void dfs_merge(int v, int b){ for(auto i : Tree[v]) if(i != b) UF.merge(v, i), dfs_merge(i, v); } vector<int> dfs_comp(int v){ vector<int> ret; function<void(int)> go = [&go,&ret](int v){ chk[v] = 1; ret.push_back(v); for(auto i : Comp[v]) if(!chk[i]) go(i); }; go(v); return move(ret); } int use[SZ]; vector<int> dfs_graph(int v){ vector<int> ret; function<void(int)> go = [&ret,&go](int v){ chk[v] = 1; ret.push_back(v); for(auto i : G[v]) if(!chk[i] && use[v] == use[i]) go(i); }; go(v); return move(ret); } vector<int> get_answer(const vector<int> &V){ vector<int> res(N, ORD[2].y); memset(use, 0, sizeof use); memset(chk, 0, sizeof chk); for(auto i : V) use[i] = 1; for(int i=0; i<N; i++){ if(chk[i]) continue; auto dfn = dfs_graph(i); dfn.resize(ORD[!use[i]].x); for(auto j : dfn) res[j] = ORD[!use[i]].y; } return res; } vector<int> find_split(int n, int a, int b, int c, vector<int> p, vector<int> q){ N = n; M = p.size(); A = a; B = b; C = c; ORD[0] = {A, 1}; ORD[1] = {B, 2}; ORD[2] = {C, 3}; sort(ORD, ORD+3); UF.clear(); for(int i=0; i<M; i++){ int s = p[i], e = q[i]; if(UF.merge(s, e)) Tree[s].push_back(e), Tree[e].push_back(s); G[s].push_back(e); G[e].push_back(s); } int cent = get_cent(0, get_sz(0)); for(auto i : Tree[cent]){ auto dfn = dfs_subtree(i, cent); if(dfn.size() >= ORD[0].x) return get_answer(dfn); } UF.clear(); for(auto i : Tree[cent]) dfs_merge(i, cent); for(int i=0; i<M; i++){ int s = UF.find(p[i]), e = UF.find(q[i]); if(s == cent || e == cent || s == e) continue; Comp[s].push_back(e); Comp[e].push_back(s); } memset(chk, 0, sizeof chk); int pv = 0; for(int i=0; i<N; i++){ if(i == cent || i != UF.find(i) || chk[i]) continue; auto dfn = dfs_comp(i); pv++; int sum = 0; for(auto j : dfn){ use[j] = pv; if((sum += UF.W[j]) >= ORD[0].x) break; } if(sum < ORD[0].x) continue; vector<int> res; for(int j=0; j<N; j++) if(use[UF.find(j)] == pv) res.push_back(j); return get_answer(res); } return vector<int>(N, 0); } #ifdef LOCAL int main(){ int n, m, a, b, c; assert(5 == scanf("%d%d%d%d%d", &n, &m, &a, &b, &c)); vector<int> p(m), q(m); for(int i=0; i<m; i++) assert(2 == scanf("%d%d", &p[i], &q[i])); vector<int> result = find_split(n, a, b, c, p, q); for (int i=0; i<(int)result.size(); i++) printf("%s%d", ((i>0)?" ":""), result[i]); printf("\n"); return 0; } #endif

Compilation message (stderr)

split.cpp: In function 'std::vector<int> dfs_subtree(int, int)':
split.cpp:60:16: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
   60 |     return move(ret);
      |            ~~~~^~~~~
split.cpp:60:16: note: remove 'std::move' call
split.cpp: In function 'std::vector<int> dfs_comp(int)':
split.cpp:74:16: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
   74 |     return move(ret);
      |            ~~~~^~~~~
split.cpp:74:16: note: remove 'std::move' call
split.cpp: In function 'std::vector<int> dfs_graph(int)':
split.cpp:85:16: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move]
   85 |     return move(ret);
      |            ~~~~^~~~~
split.cpp:85:16: note: remove 'std::move' call
split.cpp: In function 'std::vector<int> find_split(int, int, int, int, std::vector<int>, std::vector<int>)':
split.cpp:118:23: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  118 |         if(dfn.size() >= ORD[0].x) return get_answer(dfn);
      |                       ^
#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...