This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 = 30; // max types of keys
const int MAXND = 1'000'000;
struct DSU {
int p[MAXN + 10];
int k[MAXN + 10];
void init() {
memset(p, -1, sizeof(p));
}
int find(int n) {
if(p[n] < 0) return n;
return p[n] = find(p[n]);
}
void uni(int a, int b) {
a = find(a); b = find(b);
if(a != b) {
p[b] = a;
k[a] |= k[b];
}
}
} dsu[MAXK + 10];
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) {
// cerr << "(" << r1 << ", " << k1 << ") -> ";
// cerr << "(" << r2 << ", " << k2 << ")\n";
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;
vector<i32> find_reachable(vector<i32> R, vector<i32> U, vector<i32> V, vector<i32> C) {
int n = sz(R);
int m = sz(C);
For(k, 0, MAXK - 1) {
dsu[k].init();
For(r, 0, n - 1) {
dsu[k].k[r] = (1 << R[r]);
}
}
vector<vector<int>> keys(n);
For(i, 0, m - 1) {
ayaya.bilink(U[i], C[i], V[i], C[i]);
dsu[C[i]].uni(U[i], V[i]);
keys[U[i]].eb(C[i]);
keys[V[i]].eb(C[i]);
}
For(r, 0, n - 1) For(k, 0, 29) {
// 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]);
int mask = dsu[k].k[dsu[k].find(r)];
For(k2, 0, 29) if(mask & (1 << k2)) ayaya.link(r, k, r, k2);
}
int nscc = ayaya.build_scc();
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) {
cerr << reach[i] << " \n"[i == 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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |