제출 #826755

#제출 시각아이디문제언어결과실행 시간메모리
826755kevinsogoSplit the Attractions (IOI19_split)C++17
100 / 100
274 ms77544 KiB
#include <bits/stdc++.h> using namespace std; #include "split.h" using ll = long long; template<class T> using vec = vector<T>; vec<vec<int>> extract(int n, int a, int b, int c, const vec<pair<int,int>>& edges) { int e = edges.size(); assert(1 <= a and a <= b and b <= c); assert(3*a <= n); assert(2*b <= n); assert(1*c <= n); vec<vec<int>> adj(n); vec<bool> vis(n); auto get_component = [&](unordered_set<int>& nodes, int s) { for (int i : nodes) { vis[i] = false; adj[i].clear(); } assert(nodes.count(s)); for (auto [i, j] : edges) { if (nodes.count(i) and nodes.count(j)) { adj[i].push_back(j); adj[j].push_back(i); } } vis[s] = true; vec<int> que = {s}; for (int f = 0; f < que.size(); f++) { int i = que[f]; for (int j : adj[i]) { if (not vis[j]) { vis[j] = true; que.push_back(j); } } } return que; }; auto get_bccs = [&]() { vec<vec<pair<int,int>>> adj(n); for (int idx = 0; idx < e; idx++) { auto [i, j] = edges[idx]; adj[i].emplace_back(j, idx); adj[j].emplace_back(i, idx); } vec<int> low(n, -1), dsc(n, -1); vec<bool> evi(e); vec<int> eve; vec<vec<int>> bccs; int tm = 0; function<void(int)> dfs = [&](int i) { assert(dsc[i] == -1); dsc[i] = low[i] = tm++; for (auto [j, idx] : adj[i]) { if (evi[idx]) continue; eve.push_back(idx); evi[idx] = true; if (dsc[j] == -1) { dfs(j); low[i] = min(low[i], low[j]); if (low[j] >= dsc[i]) { bccs.emplace_back(); while (bccs.back().empty() or bccs.back().back() != idx) { bccs.back().push_back(eve.back()); eve.pop_back(); } } } else { low[i] = min(low[i], dsc[j]); } } }; dfs(0); assert(eve.empty()); // assert all(d >= 0 for d in dsc) // assert all(evi) // assert not eve // assert sum(map(len, bccs)) == e return bccs; }; auto bccs = get_bccs(); auto get_bctree = [&]() -> tuple<vec<vec<int>>,vec<int>,vec<int>> { vec<vec<int>> bcadj(n + bccs.size()); vec<unordered_set<int>> bcedges(n); for (int bci = 0; bci < bccs.size(); bci++) { for (int idx : bccs[bci]) { auto [i, j] = edges[idx]; bcedges[i].insert(n + bci); bcedges[j].insert(n + bci); } } int ct = 0; for (int i = 0; i < n; i++) { for (int j : bcedges[i]) { ct++; bcadj[i].push_back(j); bcadj[j].push_back(i); } } assert(ct == n + bccs.size() - 1); vec<int> bcsiz(n, 1); bcsiz.resize(n + bccs.size()); vec<int> bcpar(n + bccs.size(), -1); function<void(int)> dfs = [&](int i) { for (int j : bcadj[i]) { if (j != bcpar[i]) { bcpar[j] = i; dfs(j); bcsiz[i] += bcsiz[j]; } } }; dfs(0); assert(bcsiz[0] == n); return {bcadj, bcsiz, bcpar}; }; auto [bcadj, bcsiz, bcpar] = get_bctree(); vec<int> low(n, -1), dsc(n, -1); vec<bool> evi(e); vec<vec<pair<int,int>>> iadj(n); vec<int> isize(n), dep(n); vec<bool> inseq(n), inaseq(n); vec<int> pare(n, -1); vec<vec<int>> igs(n); for (int bci = 0; bci < bccs.size(); bci++) { vec<int>& inodes = bcadj[n + bci]; for (int i : inodes) isize[i] = bcsiz[i]; isize[bcpar[n + bci]] = n - bcsiz[n + bci]; // assert sum(isize[i] for i in inodes) == n assert(inodes.size() >= 2); int r = *max_element(inodes.begin(), inodes.end(), [&](int i, int j) { return isize[i] < isize[j]; }); for (int i : inodes) { dsc[i] = -1; iadj[i].clear(); inseq[i] = inaseq[i] = false; } for (int idx : bccs[bci]) { evi[idx] = false; auto [i, j] = edges[idx]; iadj[i].emplace_back(j, idx); iadj[j].emplace_back(i, idx); } int tm = 0; dep[r] = 0; function<void(int)> dfs = [&](int i) { assert(dsc[i] == -1); dsc[i] = low[i] = tm++; for (auto [j, idx] : iadj[i]) { if (evi[idx]) continue; evi[idx] = true; if (dsc[j] == -1) { dep[j] = dep[i] + 1; pare[j] = idx; dfs(j); low[i] = min(low[i], low[j]); } else { low[i] = min(low[i], dsc[j]); } } assert((low[i] == dsc[i]) == (i == r or inodes.size() == 2)); }; dfs(r); vec<int> aseq; if (inodes.size() == 2) { aseq = inodes; if (aseq[0] != r) reverse(aseq.begin(), aseq.end()); } else { vec<int> fseq; auto add_all = [&](vec<int> s) { reverse(s.begin(), s.end()); for(int i : s) { assert(not inseq[i]); inseq[i] = true; } for (int i : s) { igs[i].clear(); for (auto [j, idx] : iadj[i]) { if (not inseq[j] and pare[j] == idx) igs[i].push_back(j); } fseq.push_back(i); } }; add_all({r}); while (not fseq.empty()) { int i = fseq.back(); fseq.pop_back(); if (igs[i].empty()) { aseq.push_back(i); inaseq[i] = true; } else { int j = igs[i].back(); igs[i].pop_back(); int targ = max(1, dsc[i]); assert(low[j] < targ); vec<int> seq = {j}; while (dsc[seq.back()] >= targ) { for (auto [k, idx] : iadj[seq.back()]) { if (dsc[k] < targ or pare[k] == idx and low[k] == low[seq.back()]) { seq.push_back(k); break; } } // else: assert false } int l = seq.back(); seq.pop_back(); if (inaseq[l]) { reverse(seq.begin(), seq.end()); fseq.push_back(i); add_all(seq); } else { add_all(seq); fseq.push_back(i); } } } } // assert {*aseq} == {*inodes} int sz = 0; vec<int> gr, rg(aseq.rbegin(), aseq.rend()); while (sz < a) { gr.push_back(rg.back()); rg.pop_back(); sz += isize[gr.back()]; } assert(not gr.empty()); assert(not rg.empty()); if (b <= sz and a <= n - sz) { swap(gr, rg); sz = n - sz; assert(a <= sz and b <= n - sz); } if (a <= sz and b <= n - sz) { unordered_set<int> ns; for (int i = 0; i < n; i++) ns.insert(i); for (int i : gr) ns.erase(i); auto compb = get_component(ns, rg.front()); assert(compb.size() == n - sz); ns.clear(); for (int i = 0; i < n; i++) ns.insert(i); for (int i : compb) ns.erase(i); auto compa = get_component(ns, gr.front()); assert(compa.size() == sz); compa.resize(a); compb.resize(b); ns.clear(); for (int i = 0; i < n; i++) ns.insert(i); for (int i : compa) ns.erase(i); for (int i : compb) ns.erase(i); vec<int> compc(ns.begin(), ns.end()); return {compa, compb, compc}; } } return {}; } vec<int> find_split(int n, int a, int b, int c, vec<int> p, vec<int> q) { assert(p.size() == q.size()); vec<pair<int,int>> edges(p.size()); for (int i = 0; i < p.size(); i++) edges[i] = {p[i], q[i]}; vec<pair<int,int>> abci = {{a, 1}, {b, 2}, {c, 3}}; sort(abci.begin(), abci.end()); vec<int> res(n, 0); if (auto abcs = extract(n, abci[0].first, abci[1].first, abci[2].first, edges); not abcs.empty()) { assert(abci.size() == abcs.size()); for (int x = 0; x < abci.size(); x++) { auto [sz, vl] = abci[x]; assert(abcs[x].size() == sz); for (int i : abcs[x]) res[i] = vl; } } return res; }

컴파일 시 표준 에러 (stderr) 메시지

split.cpp: In lambda function:
split.cpp:32:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   32 |         for (int f = 0; f < que.size(); f++) {
      |                         ~~^~~~~~~~~~~~
split.cpp: In lambda function:
split.cpp:95:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int>, std::allocator<std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   95 |         for (int bci = 0; bci < bccs.size(); bci++) {
      |                           ~~~~^~~~~~~~~~~~~
In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from split.cpp:1:
split.cpp:111:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int>, std::allocator<std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  111 |         assert(ct == n + bccs.size() - 1);
      |                ~~~^~~~~~~~~~~~~~~~~~~~~~
split.cpp: In function 'vec<std::vector<int> > extract(int, int, int, int, vec<std::pair<int, int> >&)':
split.cpp:140:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int>, std::allocator<std::vector<int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  140 |     for (int bci = 0; bci < bccs.size(); bci++) {
      |                       ~~~~^~~~~~~~~~~~~
split.cpp:218:65: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  218 |                             if (dsc[k] < targ or pare[k] == idx and low[k] == low[seq.back()]) {
In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from split.cpp:1:
split.cpp:261:33: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  261 |             assert(compb.size() == n - sz);
      |                    ~~~~~~~~~~~~~^~~~~~~~~
split.cpp:266:33: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
  266 |             assert(compa.size() == sz);
      |                    ~~~~~~~~~~~~~^~~~~
split.cpp: In function 'vec<int> find_split(int, int, int, int, vec<int>, vec<int>)':
split.cpp:284:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  284 |     for (int i = 0; i < p.size(); i++) edges[i] = {p[i], q[i]};
      |                     ~~^~~~~~~~~~
split.cpp:290:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  290 |         for (int x = 0; x < abci.size(); x++) {
      |                         ~~^~~~~~~~~~~~~
In file included from /usr/include/c++/10/cassert:44,
                 from /usr/include/x86_64-linux-gnu/c++/10/bits/stdc++.h:33,
                 from split.cpp:1:
split.cpp:292:35: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'std::tuple_element<0, std::pair<int, int> >::type' {aka 'int'} [-Wsign-compare]
  292 |             assert(abcs[x].size() == sz);
      |                    ~~~~~~~~~~~~~~~^~~~~
#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...