Submission #932640

#TimeUsernameProblemLanguageResultExecution timeMemory
932640Programmer123Keys (IOI21_keys)C++17
37 / 100
3038 ms35064 KiB
#ifndef LOCAL
#pragma GCC optimize("O3")
#pragma GCC target("avx2,sse4.2")
#endif

#include <bits/stdc++.h>

std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) {
    std::vector<int> ans(r.size(), 0);
    int N = r.size();
    int M = u.size();
    std::vector<int> newName;
    for (int i = 0; i < N; ++i) {
        newName.push_back(i);
    }
    std::shuffle(newName.begin(), newName.end(), std::default_random_engine(std::random_device{}()));
    auto R = r;
    for (int i = 0; i < N; ++i) {
        r[newName[i]] = R[i];
    }
    for (int i = 0; i < M; ++i) {
        u[i] = newName[u[i]];
        v[i] = newName[v[i]];
        c[i] = c[i];
    }
    std::vector<std::pair<int, int>> edges[N];//{dest, type}
    for (int i = 0; i < M; ++i) {
        edges[u[i]].emplace_back(v[i], c[i]);
        edges[v[i]].emplace_back(u[i], c[i]);
    }
    std::unordered_set<int> num[N], canReach[N];
    bool eliminated[N];
    for (int i = 0; i < N; ++i) {
        eliminated[i] = false;
    }
    int actual[N];
    for (int i = 0; i < N; ++i) {
        actual[i] = i;
    }
    std::function<void(int)> Eliminate = [&](int x) {
#ifdef LOCAL
        printf("Trying to eliminate %d\n", x);
#endif
        if (eliminated[actual[x]]) return;
#ifdef LOCAL
        printf("Eliminating %d\n", x);
#endif
        eliminated[actual[x]] = true;
        num[x].clear();
        num[actual[x]].clear();
        for (auto a: canReach[x]) {
            Eliminate(a);
        }
        for (auto a: canReach[actual[x]]) {
            Eliminate(a);
        }
    };
    bool seen[N];
    for (int i = 0; i < N; ++i) {
        seen[i] = false;
    }
    std::vector<int> Seen;
    bool found[N];
    for (int i = 0; i < N; ++i) {
        found[i] = false;
    }
    std::vector<int> Found;
    int minnum = N;
    for (int i = 0; i < N; ++i) {
        for (auto x: Seen) seen[x] = false;
        Seen.clear();
        for (auto x: Found) found[x] = false;
        Found.clear();
        seen[i] = true;
        Seen.push_back(i);
        std::vector<int> next[N];
        std::queue<int> bfs;
        bfs.push(i);
        int TMP_THING = 0;
        int numseen = 1;
        while (!bfs.empty()) {
            if (numseen > minnum) {
                TMP_THING = -1;
                goto elim;
            }
            auto n = bfs.front();
            bfs.pop();
            if (!found[r[n]]) {
                found[r[n]] = true;
                Found.push_back(r[n]);
                for (auto a: next[r[n]]) {
                    if (!seen[a]) {
                        if (a < i) {
                            TMP_THING = a;
                            goto elim;
                        }
                        seen[a] = true;
                        Seen.push_back(a);
                        bfs.push(a);
                        numseen++;
                    }
                }
            }
            for (auto [x, t]: edges[n]) {
                if (seen[x]) continue;
                if (found[t]) {
                    if (x < i) {
                        TMP_THING = x;
                        goto elim;
                    }
                    seen[x] = true;
                    Seen.push_back(x);
                    bfs.push(x);
                    numseen++;
                } else {
                    next[t].push_back(x);
                }
            }
        }
        for (int j = 0; j < N; ++j) {
            if (seen[j]) {
                num[i].insert(j);
                canReach[j].insert(i);
            }
        }
        for (auto x: canReach[i]) {
            if (!seen[x]) Eliminate(x);
        }
        minnum = std::min(minnum, numseen);
        continue;
        elim:
        if (TMP_THING == -1) {
            Eliminate(i);
            continue;
        }
        TMP_THING = actual[TMP_THING];
        if (eliminated[TMP_THING]) {
            eliminated[i] = true;
            for (auto x: canReach[i]) {
                Eliminate(x);
            }
        } else {
            if (num[TMP_THING].count(i)) {
                actual[i] = TMP_THING;
                for (auto x: canReach[i]) {
                    if (!num[TMP_THING].count(x)) Eliminate(x);
                }
            } else {
                eliminated[i] = true;
                for (auto x: canReach[i]) {
                    Eliminate(x);
                }
            }
        }
    }
    size_t min = INT_MAX;
    for (int i = 0; i < N; ++i) {
        if (eliminated[i]) continue;
        if (actual[i] != i) continue;
        min = std::min(min, num[i].size());
    }
    for (int i = 0; i < N; ++i) {
        if (eliminated[i] || eliminated[actual[i]]) continue;
        ans[i] = num[actual[i]].size() == min;
    }
    auto Ans = ans;
    for (int i = 0; i < N; ++i) {
        Ans[i] = ans[newName[i]];
    }
    return Ans;
}
#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...