Submission #627270

#TimeUsernameProblemLanguageResultExecution timeMemory
627270model_codeThousands Islands (IOI22_islands)C++17
19.25 / 100
138 ms18604 KiB
// failed/solution-yoshiyuki-incorrect-random-branch-valid-cycle.cpp // Incorrect attempt of O(N^2) with Monte Carlo // After remove DAG and handle 2 separate cycles case // Pick random node with branches, search until 2 valid cycles are found // It choose a random shortest path between 0 and the start of the cycle // One counter to this solution is gen_tricky_3. // This solution MUST be WA and TLE for all values of ATTEMPT. #include "islands.h" #include <functional> #include <queue> #include <utility> #include <set> #include <variant> #include <vector> #include <cstring> #include <cassert> #include <cstdlib> #include <ctime> const int max_n = 1e5; const int ATTEMPT = 200; std::vector<int> adj[max_n+10]; std::set<int> u_adj[max_n+10]; int vis[max_n+10]; // 0 = unvisited, 1 = visited, 2 = invalid cycle bool vis_dag[max_n+10]; bool vis_candidate[max_n+10]; bool vis_path[max_n+10]; std::vector<int> has_cycle; bool excluded[max_n+10]; std::vector<std::pair<int, int> > candidate; int prev_path[max_n+10]; // Find cycle from start of branch bool find_cycle(int cur, bool init = true) { if (excluded[cur]) return false; if (!init && vis[cur] == 1) return true; if (vis[cur] == 2) return false; vis[cur] = 1; for (auto nex: u_adj[cur]) { if (find_cycle(nex, false)) return true; } return false; } // Erase DAG / Erase node with 0 outdegree void erase_dag(int cur) { if (vis_dag[cur]) return; vis_dag[cur] = true; bool has_outdegree = false; for (auto nex: adj[cur]) { erase_dag(nex); if (excluded[nex]) continue; has_outdegree = true; } if (!has_outdegree) excluded[cur] = true; return; } // Find candidates of node with branch void find_candidate(int cur, int prev) { if (excluded[cur]) return; if (vis_candidate[cur]) return; vis_candidate[cur] = true; int cnt_branch = 0; for (auto next: adj[cur]) { if (next != prev && !excluded[next]) { cnt_branch++; find_candidate(next, cur); } } if (cnt_branch >= 2) candidate.push_back({cur, prev}); return; } // Find "random" path from 0 to start of branch void find_path(int start, int finish) { memset(vis_path, false, sizeof vis_path); memset(prev_path, -1, sizeof prev_path); std::queue<int> BFS; vis_path[start] = true; BFS.push(start); while (!BFS.empty()) { if (vis_path[finish]) break; int cur = BFS.front(); BFS.pop(); for (auto nex: adj[cur]) { if (vis_path[nex]) continue; assert(vis_path[nex] == false); vis_path[nex] = true; prev_path[nex] = cur; BFS.push(nex); } } int cur = finish; while (cur != start) { cur = prev_path[cur]; vis[cur] = 2; } } void reset(int start, bool second = false) { memset(vis, 0, sizeof vis); if (second) { find_path(0, start); } vis[start] = 1; } std::variant<bool, std::vector<int>> find_journey( int N, int M, std::vector<int> U, std::vector<int> V) { srand(time(NULL)); memset(vis, 0, sizeof vis); for (int i = 0; i < M; i++) { adj[U[i]].push_back(V[i]); u_adj[U[i]].insert(V[i]); } for (int i = 0; i < N; i++) { std::random_shuffle(adj[i].begin(), adj[i].end()); } erase_dag(0); // Find 2 cycles with separate outedge from 0 int cnt = 0; for (auto start: adj[0]) { if (excluded[start]) continue; reset(start); vis[0] = 1; if (find_cycle(start)) { cnt++; has_cycle.push_back(start); } if (cnt >= 2) return true; } if (has_cycle.empty()) return false; // If 0 only has 1 outedge with cycle(s) // 2 cycles must be found here assert(has_cycle.size() == 1); find_candidate(has_cycle[0], 0); random_shuffle(candidate.begin(), candidate.end()); // Find 2 cycles among candidates int attempt = ATTEMPT; for (auto [v, prev]: candidate) { if (v == 0) continue; cnt = 0; for (auto start: adj[v]) { if (start == prev) continue; if (start == 0) continue; if (vis[start] == 2) continue; if (excluded[start]) continue; attempt--; reset(start, true); vis[v] = 1; if (find_cycle(start, true)) { cnt++; } if (cnt >= 2) { return true; } if (attempt == 0) return false; } vis[v] = 0; if (attempt == 0) return false; } return false; }
#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...