제출 #1330478

#제출 시각아이디문제언어결과실행 시간메모리
1330478DeltaStruct낙하산 고리들 (IOI12_rings)C++20
100 / 100
474 ms62996 KiB
#include <bits/stdc++.h>
using namespace std;
//#include "rings.h"

vector<vector<int>> G; set<int> D,C,F;
int n;
bool f;
multiset<pair<int,int>> Y;
vector<int> UF,SZ;
stack<pair<int,int>> S;
int root(int x){
  if (UF[x]==-1) return x;
  return root(UF[x]);
}

void Init(int N){
  n = N;
  G.assign(n,vector<int>()),D.clear(),C.clear(),Y.clear(),F.clear(),f = false;
  UF.assign(n,-1),SZ.assign(n,1);
}

bool merge(int a,int b,bool c = false){
  if (c&&root(a)==root(b)) return false;
  a = root(a),b = root(b);
  if (SZ[a]>SZ[b]) swap(a,b);
  UF[a] = b,SZ[b] += SZ[a];
  if (c) S.emplace(a,b);
  if (C.contains(a)) C.erase(a),C.emplace(b);
  return c;
}

void rollback(){
  while(!S.empty()){
    auto [a,b] = S.top(); S.pop();
    UF[a] = -1,SZ[b] -= SZ[a];
  }
}

void rebuildF(){
  if (F.size()>1){
    f = true;
    return;
  }
  Y.clear(),C.clear(),fill(UF.begin(),UF.end(),-1),fill(SZ.begin(),SZ.end(),1);
  D.clear();
  int x = *F.begin();
  G[x].clear();
  for (int i(0);i < n;++i){
    auto it = find(G[i].begin(),G[i].end(),x);
    if (it!=G[i].end()) G[i].erase(it);
    if (G[i].size()>=3) f = true;
  }
  for (int i(0);i < n;++i) for (int k:G[i]) if (i<k){
    if (root(i)==root(k)) C.emplace(root(i));
    else merge(i,k);
  }
}

void rebuild(){
  if (!F.empty()) return rebuildF();
  if (D.size()>3) f = true;
  if (f) return;
  Y.clear(),C.clear(),fill(UF.begin(),UF.end(),-1),fill(SZ.begin(),SZ.end(),1);
  vector<int> T;
  for (int i:D){
    T.emplace_back(i);
    for (int k:G[i]) T.emplace_back(k);
  }
  sort(T.begin(),T.end());
  for (int i(0);i < n;++i) for (int k:G[i]) if (i<k){
    if (binary_search(T.begin(),T.end(),i)&&binary_search(T.begin(),T.end(),k)){
      Y.emplace(i,k);
    } else {
      if (root(i)==root(k)) C.emplace(root(i));
      else merge(i,k);
    }
  }
}

void Link(int a,int b){
  if (!F.empty()&&(*F.begin()==a||*F.begin()==b)) return;
  if ((G[a].size()==2||G[b].size()==2)&&!F.empty()) f = true;
  if (f) return;
  G[a].emplace_back(b);
  if (G[a].size()==3) D.emplace(a);
  if (G[a].size()>3) F.emplace(a),rebuildF();
  if (!F.empty()&&*F.begin()==a) return;
  G[b].emplace_back(a);
  if (G[b].size()==3) D.emplace(b);
  if (G[b].size()>3) F.emplace(b),rebuildF();
  if (!F.empty()&&(*F.begin()==a||*F.begin()==b)) return;
  if (F.empty()&&(G[a].size()>=3||G[b].size()>=3)) rebuild();
  else if (root(a)==root(b)) C.emplace(root(a));
  else merge(a,b);
}

int CountCritical(){
  if (f) return 0;
  if (!F.empty()){
    if (C.empty()&&D.empty()) return 1;
    return 0;
  }
  if (!D.empty()&&!C.empty()) return 0;
  if (C.size()>1) return 0;
  if (C.size()==1) return SZ[root(*C.begin())];
  if (C.empty()&&D.empty()) return n;
  int ret = 0;
  vector<int> T;
  for (int i:D){
    T.emplace_back(i);
    for (int k:G[i]) T.emplace_back(k);
  }
  sort(T.begin(),T.end()),T.erase(unique(T.begin(),T.end()),T.end());
  for (int i:T){
    int res = 1;
    for (int k:D) if (i!=k&&find(G[k].begin(),G[k].end(),i)==G[k].end()) res = 0;
    if (res==0) continue;
    for (auto [a,b]:Y) if (a!=i&&b!=i) res &= merge(a,b,true);
    ret += res,rollback();
  }
  return ret;
}
#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...