제출 #814102

#제출 시각아이디문제언어결과실행 시간메모리
814102PixelCat열쇠 (IOI21_keys)C++17
20 / 100
3073 ms184232 KiB
#ifdef NYAOWO
#include "grader.cpp"
#endif

#include <bits/stdc++.h>
#define For(i, a, b) for(int i = a; i <= b; i++)
#define Forr(i, a, b) for(int i = a; i >= b; i--)
#define F first
#define S second
#define sz(x) ((int)x.size())
#define all(x) x.begin(), x.end()
#define eb emplace_back
#define int LL
using namespace std;
using i32 = int32_t;
using LL = long long;
using pii = pair<int, int>;

const int MAXN = 300'000;
const int MAXK = 300'000;  // max types of keys
const int MAXND = 1'000'000;

struct PairHash {
    int operator()(const pii &p1) const {
        return p1.F * MAXK + p1.S;
    }
};

struct SCC {
    int node_count = 0;
    unordered_map<pii, int, PairHash> mp;  // pair{room, key}
    pii rk[MAXND + 10];

    vector<int> adj[MAXND + 10];
    vector<int> rev[MAXND + 10];
    int vis[MAXND + 10];
    vector<int> stk;
    vector<int> scc[MAXND + 10];
    bool broken[MAXND + 10];
    
    int rk2id(int r, int k) {
        pii p(r, k);
        if(!mp.count(p)) {
            mp[p] = node_count;
            rk[node_count] = p;
            node_count++;
        }
        return mp[p];
    }
    pii id2rk(int id) {
        return rk[id];
    }

    void link(int r1, int k1, int r2, int k2) {
        int x = rk2id(r1, k1);
        int y = rk2id(r2, k2);
        adj[x].eb(y);
        rev[y].eb(x);
    }
    void bilink(int r1, int k1, int r2, int k2) {
        link(r1, k1, r2, k2);
        link(r2, k2, r1, k1);
    }

    void dfs1(int n) {
        if(vis[n] < 0) return;
        vis[n] = -1;
        for(auto &i:rev[n]) dfs1(i);
        stk.eb(n);
    }
    void dfs2(int n, int tag) {
        if(vis[n] != -1 && vis[n] != tag) broken[tag] = 1;
        if(vis[n] != -1) return;
        vis[n] = tag;
        scc[tag].eb(n);
        for(auto &i:adj[n]) dfs2(i, tag);
    }
    int build_scc() {
        memset(vis, 0, sizeof(vis));
        For(i, 0, node_count - 1) dfs1(i);
        int cur_scc = 0;
        while(sz(stk)) {
            dfs2(stk.back(), cur_scc);
            while(sz(stk) && vis[stk.back()] != -1) stk.pop_back();
            cur_scc++;
        }
        return cur_scc;
    }
} ayaya;

bool vis[MAXND + 10];
bool reach[MAXN + 10];
void dfs(int n) {
    if(vis[n]) return;
    vis[n] = 1;
    reach[ayaya.id2rk(n).F] = 1;
    for(auto &id:ayaya.adj[n]) dfs(id);
}

vector<i32> find_reachable(vector<i32> R, vector<i32> U, vector<i32> V, vector<i32> C) {
    int n = sz(R);
    int m = sz(C);

    vector<vector<int>> keys(n);
    For(i, 0, m - 1) {
        ayaya.bilink(U[i], C[i], V[i], C[i]);
        keys[U[i]].eb(C[i]);
        keys[V[i]].eb(C[i]);
    }
    For(r, 0, n - 1) {
        keys[r].eb(R[r]);
        sort(all(keys[r]));
        keys[r].erase(unique(all(keys[r])), keys[r].end());
        for(auto &k:keys[r]) ayaya.link(r, k, r, R[r]);
        // For(k, 0, 29) ayaya.link(r, k, r, R[r]);
    }
    // int nscc = ayaya.build_scc();

    vector<int> cnt(n);
    int mn = n + 48763;
    For(r, 0, n - 1) {
        memset(reach, 0, sizeof(reach));
        memset(vis, 0, sizeof(vis));
        dfs(ayaya.rk2id(r, R[r]));
        cnt[r] = 0;
        For(r2, 0, n - 1) cnt[r] += reach[r2];
        mn = min(mn, cnt[r]);
    }
    vector<i32> ans(n);
    For(i, 0, n - 1) {
        ans[i] = (cnt[i] == mn);
    }
    return ans;

    // vector<int> reach(n, -1);
    // vector<int> in_use(n, 0);
    // int mn = n + 48763;
    // For(sccid, 0, nscc - 1) if(!ayaya.broken[sccid]) {
    //     int cnt = 0;
    //     vector<int> start;
    //     for(auto &id:ayaya.scc[sccid]) {
    //         int r, k;
    //         tie(r, k) = ayaya.id2rk(id);
    //         if(k == R[r]) start.eb(r);
    //         cnt += (in_use[r] == 0);
    //         in_use[r] = 1;
    //     }
    //     for(auto &i:start) {
    //         reach[i] = cnt;
    //         mn = min(mn, cnt);
    //     }
    //     for(auto &id:ayaya.scc[sccid]) {
    //         in_use[ayaya.id2rk(id).F] = 0;
    //     }
    // }

    // vector<i32> ans(n);
    // For(i, 0, n - 1) {
    //     ans[i] = (reach[i] == mn);
    // }
    // return ans;
}

/*

4 5
0 1 1 2
0 1 0
0 2 0
1 2 1
1 3 0
3 1 2

0 1 1 0


7 10
0 1 1 2 2 1 2
0 1 0
0 2 0
1 2 1
1 3 0
2 3 0
3 4 1
3 5 2
4 5 0
4 6 2
5 6 1

0 1 1 0 1 0 1


3 1
0 0 0
0 1 0

0 0 1

*/
#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...