Submission #932640

#TimeUsernameProblemLanguageResultExecution timeMemory
932640Programmer123Keys (IOI21_keys)C++17
37 / 100
3038 ms35064 KiB
#ifndef LOCAL #pragma GCC optimize("O3") #pragma GCC target("avx2,sse4.2") #endif #include <bits/stdc++.h> std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) { std::vector<int> ans(r.size(), 0); int N = r.size(); int M = u.size(); std::vector<int> newName; for (int i = 0; i < N; ++i) { newName.push_back(i); } std::shuffle(newName.begin(), newName.end(), std::default_random_engine(std::random_device{}())); auto R = r; for (int i = 0; i < N; ++i) { r[newName[i]] = R[i]; } for (int i = 0; i < M; ++i) { u[i] = newName[u[i]]; v[i] = newName[v[i]]; c[i] = c[i]; } std::vector<std::pair<int, int>> edges[N];//{dest, type} for (int i = 0; i < M; ++i) { edges[u[i]].emplace_back(v[i], c[i]); edges[v[i]].emplace_back(u[i], c[i]); } std::unordered_set<int> num[N], canReach[N]; bool eliminated[N]; for (int i = 0; i < N; ++i) { eliminated[i] = false; } int actual[N]; for (int i = 0; i < N; ++i) { actual[i] = i; } std::function<void(int)> Eliminate = [&](int x) { #ifdef LOCAL printf("Trying to eliminate %d\n", x); #endif if (eliminated[actual[x]]) return; #ifdef LOCAL printf("Eliminating %d\n", x); #endif eliminated[actual[x]] = true; num[x].clear(); num[actual[x]].clear(); for (auto a: canReach[x]) { Eliminate(a); } for (auto a: canReach[actual[x]]) { Eliminate(a); } }; bool seen[N]; for (int i = 0; i < N; ++i) { seen[i] = false; } std::vector<int> Seen; bool found[N]; for (int i = 0; i < N; ++i) { found[i] = false; } std::vector<int> Found; int minnum = N; for (int i = 0; i < N; ++i) { for (auto x: Seen) seen[x] = false; Seen.clear(); for (auto x: Found) found[x] = false; Found.clear(); seen[i] = true; Seen.push_back(i); std::vector<int> next[N]; std::queue<int> bfs; bfs.push(i); int TMP_THING = 0; int numseen = 1; while (!bfs.empty()) { if (numseen > minnum) { TMP_THING = -1; goto elim; } auto n = bfs.front(); bfs.pop(); if (!found[r[n]]) { found[r[n]] = true; Found.push_back(r[n]); for (auto a: next[r[n]]) { if (!seen[a]) { if (a < i) { TMP_THING = a; goto elim; } seen[a] = true; Seen.push_back(a); bfs.push(a); numseen++; } } } for (auto [x, t]: edges[n]) { if (seen[x]) continue; if (found[t]) { if (x < i) { TMP_THING = x; goto elim; } seen[x] = true; Seen.push_back(x); bfs.push(x); numseen++; } else { next[t].push_back(x); } } } for (int j = 0; j < N; ++j) { if (seen[j]) { num[i].insert(j); canReach[j].insert(i); } } for (auto x: canReach[i]) { if (!seen[x]) Eliminate(x); } minnum = std::min(minnum, numseen); continue; elim: if (TMP_THING == -1) { Eliminate(i); continue; } TMP_THING = actual[TMP_THING]; if (eliminated[TMP_THING]) { eliminated[i] = true; for (auto x: canReach[i]) { Eliminate(x); } } else { if (num[TMP_THING].count(i)) { actual[i] = TMP_THING; for (auto x: canReach[i]) { if (!num[TMP_THING].count(x)) Eliminate(x); } } else { eliminated[i] = true; for (auto x: canReach[i]) { Eliminate(x); } } } } size_t min = INT_MAX; for (int i = 0; i < N; ++i) { if (eliminated[i]) continue; if (actual[i] != i) continue; min = std::min(min, num[i].size()); } for (int i = 0; i < N; ++i) { if (eliminated[i] || eliminated[actual[i]]) continue; ans[i] = num[actual[i]].size() == min; } auto Ans = ans; for (int i = 0; i < N; ++i) { Ans[i] = ans[newName[i]]; } 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...