이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include<bits/stdc++.h>
using namespace std;
#define sz(a) (int)(a.size())
#define fi first
#define se second
typedef pair<int,int> pii;
//make a graph, u->v if you start reach v starting from u
//observation if u is a min scc then v must be in a min scc too!
//so if we know u->v is on the graph we dont need to consider edges from u anymore
const int MAXN = 3e5+5;
vector<pii>adj[MAXN];
int isroot[MAXN],nxt[MAXN];
int node_par[MAXN],node_sz[MAXN],tot[MAXN];
int comp_par[MAXN],comp_sz[MAXN];
set<int> keys[MAXN];
map<int,vector<int>>edges[MAXN];
queue<pii>q;
int find_node(int v){
if(node_par[v] == v)return v;
return node_par[v] = find_node(node_par[v]);
}
int find_comp(int v){
if(comp_par[v] == v)return v;
return comp_par[v] = find_comp(comp_par[v]);
}
void merge_node(int u,int v){
u = find_node(u);
v = find_node(v);
if(u == v)return;
if(node_sz[u] > node_sz[v])swap(u,v);
for(int type:keys[u]){
keys[v].insert(type);
if(edges[v].find(type) != edges[v].end()){
for(int x:edges[v][type])q.push({v,x});
edges[v].erase(type);
}
}
for(auto z:edges[u]){
int type = z.fi;
vector<int>ed = z.se;
if(keys[v].find(type) != keys[v].end()){
for(int x:ed)q.push({u,x});
}else{
for(int x:ed)edges[v][type].push_back(x);
}
}
node_par[u] = v;
node_sz[v] += node_sz[u];
tot[v] += tot[u];
}
void merge_comp(int u,int v){
u = find_comp(u);
v = find_comp(v);
if(u == v)return;
if(comp_sz[u] > comp_sz[v])swap(u,v);
comp_par[u] = v;
comp_sz[v] += comp_sz[u];
}
//
vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) {
int n = sz(r);
vector<int>ans(n,0);
for(int i=0;i<n;i++){
nxt[i] = i;
node_par[i] = comp_par[i] = i;
node_sz[i] = comp_sz[i] = 1;
isroot[i] = 1;
tot[i] = 1; //number of rooms in node
keys[i].insert(r[i]);
}
for(int i=0;i<sz(u);i++){
if(c[i] == r[u[i]])q.push({u[i],v[i]});
else {
node_sz[u[i]]++;
edges[u[i]][c[i]].push_back(v[i]);
}
swap(u[i],v[i]);
if(c[i] == r[u[i]])q.push({u[i],v[i]});
else {
node_sz[u[i]]++;
edges[u[i]][c[i]].push_back(v[i]);
}
}
//cout<<"TES"<<'\n';
while(!q.empty()){
int u = q.front().fi;
int v = q.front().se;
q.pop();
u = find_node(u);
v = find_node(v);
if(u == v)continue; //same guy
if(!isroot[u])continue; //edge not from a root
//cout<<u<<" "<<v<<'\n';
if(find_comp(u) != find_comp(v)){
nxt[u] = v;
isroot[u] = 0;
merge_comp(u,v);
continue;
}
//same comp need to compress cycle
vector<int>path;
while(v != u){
path.push_back(v);
v = find_node(nxt[v]);
}
//cout<<"path"<<'\n';
//for(int x:path)cout<<x<<" ";
//cout<<'\n';
for(int x:path)merge_node(u,x);
u = find_node(u);
nxt[u] = u;
isroot[u] = 1;
}
int mn = n;
for(int i=0;i<n;i++){
if(i != find_node(i))continue;
int j = nxt[i];
if(find_node(j) == i)mn = min(mn,tot[i]);
}
vector<bool>good(n,0);
for(int i=0;i<n;i++){
if(i != find_node(i))continue;
int j = nxt[i];
if(find_node(j) == i && mn == tot[i])good[i] = i;
}
for(int i=0;i<n;i++){
if(good[find_node(i)])ans[i] = 1;
}
return ans;
}
# | 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... |