Submission #1091425

#TimeUsernameProblemLanguageResultExecution timeMemory
1091425ThegeekKnight16낙하산 고리들 (IOI12_rings)C++17
100 / 100
1488 ms256176 KiB
#include <bits/stdc++.h>
using namespace std;
class Dsu
{
protected:
    vector<int> pai, sub, grau;
    bool isCicle;
    int maxGrau;

public:
    Dsu (int N = 0) : pai(N), sub(N, 1), grau(N, 0), isCicle(0), maxGrau(0) {iota(pai.begin(), pai.end(), 0);}

    int find(int v) {return pai[v] = (pai[v] == v ? v : find(pai[v]));}
    void une(int x, int y)
    {
        grau[x]++; grau[y]++;
        maxGrau = max({maxGrau, grau[x], grau[y]});
        x = find(x), y = find(y);
        if (x == y) {isCicle = 1; return;}
        if (sub[x] < sub[y]) swap(x, y);
        pai[y] = x; sub[x] += sub[y];
    }
    bool isGood() {return !isCicle && (maxGrau < 3);}
};

vector<set<int>> grafo;
vector<int> pai, sub, grau;
vector<bool> isCicle;
int critNum = 0, cicleNum = 0, degreeNum = 0, degreeV;
vector<int> tam3;
vector<pair<int, int>> edges;
map<int, Dsu> without;
int N;

void Init(int _N)
{
    N = _N;
    pai.resize(N); iota(pai.begin(), pai.end(), 0);
    sub.resize(N); fill(sub.begin(), sub.end(), 1);
    grau.resize(N); fill(grau.begin(), grau.end(), 0);
    isCicle.resize(N); fill(isCicle.begin(), isCicle.end(), false);
    grafo.clear(); grafo.resize(N); edges.clear(); tam3.clear();
    without.clear();
    critNum = N, cicleNum = 0, degreeNum = 0;
}

int find(int v) {return pai[v] = (pai[v] == v ? v : find(pai[v]));}
void LinkCicle(int A, int B)
{
    if (critNum == 0) return;
    int P = find(A);
    cicleNum -= isCicle[P];
    isCicle[P] = 1;
    cicleNum += isCicle[P];
    if (cicleNum > 1) critNum = 0;
    else critNum = sub[P];
}
void Link3(int A, int B)
{
    if (tam3.size() > 3) {critNum = 0; return;}
    set<int> poss(tam3.begin(), tam3.end());
    for (auto x : tam3)
        for (auto viz : grafo[x])
            poss.insert(viz);

    critNum = 0;
    for (auto x : poss)
    {
        if (!without.count(x))
        {
            without[x] = Dsu(N);
            auto &atual = without[x];
            for (auto [i, j] : edges)
                if (i != x && j != x)
                    atual.une(i, j);
        }
        else if (A != x && B != x) without[x].une(A, B);
        critNum += without[x].isGood();
    }
}
void LinkDegree(int A, int B)
{
    if (A == degreeV || B == degreeV) return;
    without.begin()->second.une(A, B);
    critNum = without.begin()->second.isGood();
}
void buildDegree()
{
    without.clear();
    without[degreeV] = Dsu(N);
    for (auto [A, B] : edges) LinkDegree(A, B);
}

void Link(int A, int B)
{
    edges.emplace_back(A, B);
    if (critNum == 0) return;
    if (degreeNum) {LinkDegree(A, B); return;}
    grafo[A].insert(B), grafo[B].insert(A);

    degreeNum -= (grau[A] >= 4), degreeNum -= (grau[B] >= 4);
    grau[A]++; grau[B]++;
    degreeNum += (grau[A] >= 4), degreeNum += (grau[B] >= 4);
    if (degreeNum > 1) {critNum = 0; return;}
    else if (degreeNum) {degreeV = (grau[A] >= 4 ? A : B); buildDegree(); return;}

    if (grau[A] == 3) tam3.push_back(A);
    if (grau[B] == 3) tam3.push_back(B);
    if (!tam3.empty()) {Link3(A, B); return;}

    int PA = find(A), PB = find(B);
    if (PA == PB) {LinkCicle(A, B); return;}
    if (sub[PA] < sub[PB]) swap(PA, PB);
    pai[PB] = PA; sub[PA] += sub[PB]; isCicle[PA] = (isCicle[PA] || isCicle[PB]);
}

int CountCritical() {return critNum;}
#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...