Submission #994532

#TimeUsernameProblemLanguageResultExecution timeMemory
994532CSQ31Keys (IOI21_keys)C++17
0 / 100
98 ms244564 KiB
#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 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;
queue<int>unlocked[MAXN];
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])unlocked[v].push(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)unlocked[u].push(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];
}
void dfs(int u){
	u = find_node(u);
	if(find_node(nxt[u]) != u)return;
	while(!unlocked[u].empty() && find_node(unlocked[u].front()) == u)unlocked[u].pop();
	if(unlocked[u].empty())return;
 
	int v = unlocked[u].front();
	v = find_node(v);
	unlocked[u].pop();
	if(find_comp(u) != find_comp(v)){
		nxt[u] = v;
		merge_comp(u,v);
	}else{
		vector<int>path;
		while(v != u){
			path.push_back(v);
			v = find_node(nxt[v]);
		}
		for(int x:path)merge_node(u,x);
		u = find_node(u);
		nxt[u] = u;
	}
	dfs(v);
}
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++){
		node_par[i] = comp_par[i] = nxt[i] = i;
		node_sz[i] = comp_sz[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]])unlocked[u[i]].push(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]])unlocked[u[i]].push(v[i]);
		else {
			node_sz[u[i]]++;
			edges[u[i]][c[i]].push_back(v[i]);
		}
	}
	for(int i=0;i<n;i++)dfs(i);
	// 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(find_node(nxt[u]) != u)continue; //edge not from a root
	// 	//cout<<u<<" "<<v<<'\n';
	// 	if(find_comp(u) != find_comp(v)){
	// 		nxt[u] = v;
	// 		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]);
	// 	}
	// 	for(int x:path)merge_node(u,x);
	// 	u = find_node(u);
	// 	nxt[u] = u;
	// }
	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 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...