Submission #447072

#TimeUsernameProblemLanguageResultExecution timeMemory
447072blue열쇠 (IOI21_keys)C++17
0 / 100
32 ms47284 KiB
#include "keys.h" #include <vector> #include <iostream> #include <set> using namespace std; struct corridor { int v; int c; }; bool operator < (corridor A, corridor B) { return A.c < B.c; } const int maxN = 300'000; int N; int M; struct out_comp { int i; //i = scc root of component }; bool operator < (out_comp A, out_comp B) { return A.i < B.i; }; set<int> leaf_components; //FG roots without good edges set<int> out_components; //FG roots with good edges vector<int> scc_parent(maxN); vector<int> scc_size(maxN, 1); multiset<corridor> bad_corridors[maxN]; //nodes, not labels set<int> good_corridors[maxN]; set<int> keys[maxN]; int scc_root(int u) { while(scc_parent[u] != u) u = scc_parent[u]; return u; } vector<int> func_parent(maxN); //all are scc roots vector<int> func_root(maxN); void add_good_edge(int u, int v) { u = scc_root(u); v = scc_root(v); if(u == v) return; good_corridors[u].insert(v); if(leaf_components.find(u) != leaf_components.end()) { leaf_components.erase(u); out_components.insert(u); } } void scc_join(int u, int v) { u = scc_root(u); v = scc_root(v); if(u == v) return; if(scc_size[u] < scc_size[v]) swap(u, v); scc_parent[v] = u; scc_size[u] += scc_size[v]; for(int k: keys[v]) { while(1) { multiset<corridor>::iterator it = bad_corridors[u].find(corridor{-1, k}); if(it == bad_corridors[u].end()) break; add_good_edge(u, it->v); bad_corridors[u].erase(it); } keys[u].insert(k); } keys[v].clear(); for(corridor d: bad_corridors[v]) { // if(scc_root(d.v) == scc_root(d.u)) continue; if(keys[u].find(d.c) == keys[u].end()) { bad_corridors[u].insert(d); } else { add_good_edge(u, d.v); } } for(int h: good_corridors[v]) { good_corridors[u].insert(h); } } bool scc_same(int u, int v) { return scc_root(u) == scc_root(v); } void execute(int x, int y) //add edge x -> y; { x = scc_root(x); y = scc_root(y); if(func_root[y] != x) { out_components.erase(x); func_parent[x] = y; func_root[x] = y; } else if(func_root[y] == x) { vector<int> mergers(1, x); for(int z = y; z != x; z = func_parent[ scc_root(z) ]) mergers.push_back(z); for(int i = 0; i+1 < mergers.size(); i++) { scc_join(mergers[i], mergers[i+1]); } } } vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) { // cerr << "check 1\n"; N = r.size(); M = u.size(); for(int i = 0; i < N; i++) { scc_parent[i] = i; func_parent[i] = i; func_root[i] = i; } // cerr << "check 2\n"; for(int j = 0; j < M; j++) { if(r[ u[j] ] == c[j]) good_corridors[ u[j] ].insert( v[j] ); else bad_corridors[ u[j] ].insert(corridor{v[j], c[j]}); if(r[ v[j] ] == c[j]) good_corridors[ v[j] ].insert( u[j] ); else bad_corridors[ v[j] ].insert(corridor{u[j], c[j]}); } // cerr << "check 3\n"; for(int i = 0; i < N; i++) { if(good_corridors[i].size() > 0) out_components.insert(i); else leaf_components.insert(i); } // cerr << "check 4\n"; while(out_components.size() >= 1) { int x = *out_components.begin(); int y = *good_corridors[x].begin(); out_components.erase(x); good_corridors[x].erase(y); if(good_corridors[x].size() >= 1) out_components.insert(x); else leaf_components.insert(x); execute(scc_root(x), scc_root(y)); //add an edge x -> y } // cerr << "check 5\n"; vector<int> res_list; int min_reach = 1e9; for(int i = 0; i < N; i++) { int I = scc_root(i); while(!good_corridors[I].empty()) { int x = *good_corridors[I].begin(); if(scc_root(x) == I) { good_corridors[I].erase(x); continue; } break; } if(!good_corridors[I].empty() || scc_root(func_parent[i]) != scc_root(i) ) { // cerr << "i = " << i << ", this is not a root\n"; continue; } if(scc_size[I] > min_reach) continue; else if(scc_size[I] == min_reach) { // cerr << "case Z\n"; res_list.push_back(i); // cerr << "RL = "; // for(int r1: res_list) cerr << r1 << ' '; // cerr << '\n'; } else { // cerr << "case Y\n"; res_list.clear(); res_list.push_back(i); min_reach = scc_size[I]; } // cerr << "i = " << i << ", reachability = " << scc_size[I] << '\n'; } // cerr << "check 6\n"; // for(int i = 0; i < N; i++) cerr << "root of " << i << " = " << scc_root(i) << '\n'; // for(int i = 0; i < N; i++) cerr << "FG parent of " << scc_root(i) << " = " << func_parent[i] << '\n'; vector<int> res(N); for(int R: res_list) res[R] = 1; return res; }

Compilation message (stderr)

keys.cpp: In function 'void execute(int, int)':
keys.cpp:156:28: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  156 |         for(int i = 0; i+1 < mergers.size(); i++)
      |                        ~~~~^~~~~~~~~~~~~~~~
#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...