제출 #1329711

#제출 시각아이디문제언어결과실행 시간메모리
1329711SmuggingSpun열쇠 (IOI21_keys)C++20
100 / 100
488 ms62516 KiB
#include<bits/stdc++.h>
using namespace std;
template<class T>bool minimize(T& a, T b){
  if(a > b){
    a = b;
    return true;
  }
  return false;
}
const int lim = 3e5 + 5;
int n, m;
vector<int>r, u, v, c, g[lim];
namespace sub1{
  vector<int>solve(){
    int best_cnt = n + 1, cnt;
    vector<int>color(n, 0), ans;
    vector<bool>vis(n);
    function<void(int)>dfs;
    dfs = [&] (int s){
      vis[s] = true;
      cnt++;
      for(int& i : g[s]){
        int d = u[i] ^ v[i] ^ s;
        if(!vis[d]){
          dfs(d);
        }
      }
    };
    for(int i = 0; i < n; i++){
      if(r[i] == 0){
        cnt = 0;
        fill(vis.begin(), vis.end(), false);
        dfs(i);
      }
      else{
        cnt = 1;
      }
      if(minimize(best_cnt, cnt)){
        ans.clear();
      }
      if(best_cnt == cnt){
        ans.push_back(i);
      }
    }
    for(int& x : ans){
      color[x] = 1;
    }
    return color;
  }
}
namespace sub23{
  vector<int>solve(){
    vector<vector<int>>vc(n);
    vector<int>lab(n), siz(n), ans(n, 0), small;
    auto find_set = [&] (int i){
      while(i != lab[i]){
        i = lab[i] = lab[lab[i]];
      }
      return i;
    };
    auto merge = [&] (int i, int j){
      if((i = find_set(i)) != (j = find_set(j))){
        if(vc[i].size() < vc[j].size()){
          swap(i, j);
        }
        siz[lab[j] = i] += siz[j];
        for(int& k : vc[j]){
          vc[i].push_back(k);
        }
      }
    };
    for(int i = 0, best_cnt = n + 1; i < n; i++){
      for(int j = 0; j < n; j++){
        siz[lab[j] = j] = 1;
        vc[j].clear();
        vc[j].push_back(r[j]);
      }
      vector<vector<int>>ec(n);
      for(int j = 0; j < m; j++){
        ec[c[j]].push_back(j);
      }
      while(!vc[find_set(i)].empty()){
        int x = vc[find_set(i)].back();
        vc[find_set(i)].pop_back();
        for(int& k : ec[x]){
          merge(u[k], v[k]);
        }
        ec[x].clear();
      }
      if(minimize(best_cnt, siz[find_set(i)])){
        small.clear();
      }
      if(best_cnt == siz[find_set(i)]){
        small.push_back(i);
      }
    }
    for(int& x : small){
      ans[x] = 1;
    }
    return ans;
  }
}
namespace sub4{
  vector<int>solve(){
    queue<int>q;
    for(int i = 0; i < m; i++){
      q.push(i);
    }
    vector<int>mask(n);
    for(int i = 0; i < n; i++){
      mask[i] = 1 << r[i];
    }
    auto update_from_to = [&] (int u, int v, int c){
      if(mask[u] >> c & 1){
        int x = mask[u];
        if((mask[u] |= mask[v]) != x){
          for(int& i : g[u]){
            q.push(i);
          }
        }
      }
    };
    while(!q.empty()){
      int i = q.front();
      q.pop();
      update_from_to(u[i], v[i], c[i]);
      update_from_to(v[i], u[i], c[i]);
    }
    for(int i = 0; i < n; i++){
      g[i].clear();
    }
    for(int i = 0; i < m; i++){
      if(mask[u[i]] >> c[i] & 1){
        g[u[i]].push_back(v[i]);
      }
      if(mask[v[i]] >> c[i] & 1){
        g[v[i]].push_back(u[i]);
      }
    }
    vector<int>color(n), low(n), num(n, 0), stk, siz;
    vector<bool>out(n, false);
    int tdfs = 0, cnt_color = 0;
    function<void(int)>dfs;
    dfs = [&] (int s){
      stk.push_back(s);
      low[s] = num[s] = ++tdfs;
      for(int& d : g[s]){
        if(!out[d]){
          if(num[d] == 0){
            dfs(d);
            minimize(low[s], low[d]);
          }
          else{
            minimize(low[s], num[d]);
          }
        }
      }
      if(low[s] == num[s]){
        int siz_color = 0;
        while(true){
          int x = stk.back();
          stk.pop_back();
          color[x] = cnt_color;
          out[x] = true;
          siz_color++;
          if(x == s){
            break;
          }
        }
        siz.push_back(siz_color);
        cnt_color++;
      }
    };
    for(int i = 0; i < n; i++){
      if(num[i] == 0){
        dfs(i);
      }
    }
    vector<bool>avai(cnt_color, true), best_col(cnt_color, false);
    for(int i = 0; i < n; i++){
      for(int& j : g[i]){
        if(color[i] != color[j]){
          avai[color[i]] = false;
        }
      }
    }
    vector<int>cand_col;
    for(int i = 0, best_cnt = n + 1; i < cnt_color; i++){
      if(avai[i]){
        if(minimize(best_cnt, siz[i])){
          cand_col.clear();
        }
        if(best_cnt == siz[i]){
          cand_col.push_back(i);
        }
      }
    }
    for(int& x : cand_col){
      best_col[x] = true;
    }
    vector<int>ans(n, 0);
    for(int i = 0; i < n; i++){
      if(best_col[color[i]]){
        ans[i] = 1;
      }
    }
    return ans;
  }
}
namespace sub5{
  int best_size = lim, lab[lim];
  bitset<lim>can_color, vis, no_merge;
  vector<int>ans, ver_at_col[lim];
  int find_set(int i){
    while(i != lab[i]){
      i = lab[i] = lab[lab[i]];
    }
    return i;
  }
  void bfs(int root){
    queue<int>q;
    q.push(root);
    bool flag = false;
    vector<int>vertex, remain, in_color;
    while(!q.empty()){
      int s = q.front();
      q.pop();
      if(find_set(s) != root){
        vis[lab[root] = find_set(s)] = flag = true;
        break;
      }
      if(!vis[s]){
        vertex.push_back(s);
        vis[s] = can_color[r[s]] = true;
        in_color.push_back(r[s]);
        for(int& x : ver_at_col[r[s]]){
          q.push(x);
        }
        ver_at_col[r[s]].clear();
        for(int& i : g[s]){
          int d = u[i] ^ v[i] ^ s;
          if(can_color[c[i]]){
            q.push(d);
          }
          else{
            ver_at_col[c[i]].push_back(d);
            remain.push_back(c[i]);
          }
        }
      }
    }
    for(int& x : in_color){
      can_color[x] = false;
    }
    for(int& x : remain){
      ver_at_col[x].clear();
    }
    if(!flag){
      if(minimize(best_size, int(vertex.size()))){
        ans.clear();
      }
      if(best_size == vertex.size()){
        for(int& i : vertex){
          ans.push_back(i);
        }
      }
      no_merge[root] = true;
    }
  }
  vector<int>solve(){
    iota(lab, lab + n, 0);
    can_color.reset();
    vis.reset();
    no_merge.reset();
    while(true){
      bool need = true;
      vis.reset();
      for(int i = 0; i < n; i++){
        if(!no_merge[i] && !vis[i] && find_set(i) == i){
          bfs(i);
          need = false;
        }
      }
      if(need){
        break;
      }
    }
    vector<int>color(n, 0);
    for(int& i : ans){
      color[i] = 1;
    }
    return color;
  }
}
vector<int>find_reachable(vector<int>_r, vector<int>_u, vector<int>_v, vector<int>_c){
  swap(r, _r);
  swap(u, _u);
  swap(v, _v);
  swap(c, _c);
  m = u.size();
  for(int i = 0; i < m; i++){
    g[u[i]].push_back(i);
    g[v[i]].push_back(i);
  }
  if(max(n = r.size(), m) <= 200 && *max_element(c.begin(), c.end()) == 0){
    return sub1::solve();
  }
  if(max(n, m) <= 2000){
    return sub23::solve();
  }
  if(max(*max_element(r.begin(), r.end()), *max_element(c.begin(), c.end())) <= 29){
    return sub4::solve();
  }
  return sub5::solve();
}
#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...