Submission #435737

#TimeUsernameProblemLanguageResultExecution timeMemory
435737bicsiKeys (IOI21_keys)C++17
100 / 100
1814 ms114664 KiB
#include <bits/stdc++.h>
 
using namespace std;
 
struct Solver {
  int n;
  vector<vector<int>> active;
  vector<multimap<int, int>> inactive;
  vector<set<int>> cols;
  vector<int> parent, df, link, bad;
 
  Solver(int n) : 
      n(n), active(n), inactive(n), cols(n),
      parent(n, -1), df(n, -1), link(n, -1), bad(n, 0) {}
 
  void AddEdge(int u, int v, int c) {
    if (cols[u].count(c))
      active[u].push_back(v);
    else 
      inactive[u].emplace(c, v);
  }
  void AddCol(int u, int c) {
    while (true) {
      auto it = inactive[u].find(c);
      if (it == inactive[u].end()) break;
      active[u].push_back(it->second);
      inactive[u].erase(it);
    }
    cols[u].insert(c);
  }
 
  void merge(int node, int anc) {
    while (true) {
      node = find(node);
      anc = find(anc);
      if (node == anc) return;
      int par = find(parent[node]);
      assert(par != node);
      link[node] = par;
      if (active[node].size() + cols[node].size() + inactive[node].size() > 
          active[par].size() + cols[par].size() + inactive[par].size()) {
        swap(active[node], active[par]);
        swap(cols[node], cols[par]);
        swap(inactive[node], inactive[par]);
        swap(bad[node], bad[par]);
      }
      for (auto x : cols[node])
        AddCol(par, x);
      for (auto x : active[node])
        active[par].push_back(x);
      for (auto [c, x] : inactive[node])
        AddEdge(par, x, c);
      bad[par] |= bad[node];
 
      inactive[node].clear();
      active[node].clear();
      cols[node].clear();
      bad[node] = 0;
    }
  }
 
  int find(int x) {
    if (link[x] == -1) return x;
    return link[x] = find(link[x]);
  }
 
  void dfs(int node, int par) {
    df[node] = 0;
    parent[node] = par;
    while (true) {
      node = find(node);
      if (active[node].empty()) break;
      int vec = active[node].back();
      active[node].pop_back();
      vec = find(vec);
      if (vec == node) continue;
      if (df[vec] == -1) {
        dfs(vec, node);
        if (find(vec) != find(node))
          bad[find(node)] = 1;
      } else if (df[vec] == 0) {
        merge(node, vec);
      } else {
        bad[find(node)] = 1;
      }
    }
    df[node] = 1;
  }
 
  vector<int> Solve() {
    for (int i = 0; i < n; ++i) 
      if (find(i) == i && df[i] == -1)
        dfs(i, -1);
    
    vector<int> ret(n, 0), sz(n, 0);
    int min_sz = 1e9;
    for (int i = 0; i < n; ++i) {
      if (bad[find(i)])
        continue;
      sz[find(i)] += 1;
    }
    for (int i = 0; i < n; ++i) {
      if (bad[find(i)])
        continue;
      min_sz = min(min_sz, sz[find(i)]);
    }
    for (int i = 0; i < n; ++i) {
      if (bad[find(i)])
        continue;
      ret[i] = (sz[find(i)] == min_sz);
    }
    return ret;
  }
 
};
 
vector<int> find_reachable(
    vector<int> r, vector<int> u, 
    vector<int> v, vector<int> c) {
	int n = r.size(), m = u.size();
  Solver S(n);
  for (int i = 0; i < n; ++i)
    S.AddCol(i, r[i]);
  for (int i = 0; i < m; ++i) {
    S.AddEdge(u[i], v[i], c[i]);
    S.AddEdge(v[i], u[i], c[i]);
  }
  return S.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...