제출 #997702

#제출 시각아이디문제언어결과실행 시간메모리
9977020npataKeys (IOI21_keys)C++17
100 / 100
857 ms258652 KiB
using namespace std;
#include<bits/stdc++.h>

#define vec vector

struct State {
	map<int, vec<int>> locked_edgs;
	vec<int> stk;
	set<int> merged;
	set<int> keys;
};



const int N = 300'005;

vec<pair<int, int>> g[N];
bool processed[N];
set<int> top;
int node_keys[N];
int ans[N];
State states[N];

void merge(int u, int v) {
	if(states[u].merged.size() < states[v].merged.size()) swap(states[u], states[v]);
	State& s1 = states[u];
	State& s2 = states[v];

	for(int u : s2.merged) {
		s1.merged.insert(u);
	}
	for(int k : s2.keys) {
		if(s1.locked_edgs.find(k) != s1.locked_edgs.end()) {
			for(int v : s1.locked_edgs[k]) {
				s1.stk.push_back(v);
			}
			s1.locked_edgs.erase(k);
		}
		s1.keys.insert(k);
	}
	for(auto edgs : s2.locked_edgs) {
		int k = edgs.first;
		if(s1.keys.find(k) != s1.keys.end()) {
			for(int v : edgs.second) {
				s1.stk.push_back(v);
			}
		}
		else {
			for(int v : edgs.second) {
				s1.locked_edgs[k].push_back(v);
			}
		}
	}
	for(int u : s2.stk) {
		s1.stk.push_back(u);
	}
}

int dfs(int u) {
	top.insert(u);

	//TODO: IF this breaks it's because of this reference which might change after merge maybe??
	State& state = states[u];
	state.keys.insert(node_keys[u]);
	state.merged.insert(u);

	//cerr << "U: " << u << '\n';
	for(auto edg : g[u]) {
		int v = edg.first;
		int k = edg.second;

		if(state.keys.find(k) != state.keys.end()) state.stk.push_back(v);
		else { state.locked_edgs[k].push_back(v); }
	}

	while(state.stk.size() > 0) {
		int v = state.stk.back();
		state.stk.pop_back();
		//cerr << "V: " << v << '\n';

		if(processed[v]) {
			for(int w : state.merged) {
				processed[w] = true;
			}
			//cerr << "HIT PROCESSED" << '\n';
			return -1;
		}
		else if(state.merged.find(v) != state.merged.end()) {
			//cerr << "IN MERGED" << '\n';
			continue;
		}
		else if(top.find(v) != top.end()) {
			//cerr << "AT TOP" << '\n';
			return v;
		}
		else {
			auto res = dfs(v);
			if(res == -1) {
				for(int w : state.merged) {
					processed[w] = true;
				}
				//cerr << "DFS RETURNED LEAF FOUND" << '\n';
				return -1;
			}
			else {
				merge(u, v);
				state = states[u];
				if(state.merged.find(res) == state.merged.end()) {
					//cerr << "MERGING IT UPWARDS" << '\n';
					return res;
				}
				//cerr << "MERGED" << '\n';
			}
		}
	}

	//cerr << "IS A PREORDER LEAF" << '\n';
	for(int v : state.merged) {
		ans[v] = state.merged.size();
		processed[v] = true;
	}
	return -1;
}

std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) {
	int n = r.size();
	int m = u.size();

	for(int i = 0; i<n; i++) {
		processed[i] = false;
		g[i] = {};
		ans[i] = n;
		node_keys[i] = r[i];
		states[i] = {};
	}

	for(int i = 0; i<m; i++) {
		g[u[i]].push_back({v[i], c[i]});
		g[v[i]].push_back({u[i], c[i]});
	}

	for(int i = 0; i<n; i++) {
		if(processed[i]) continue;
		top = {};
		auto res = dfs(i);
		assert(processed[i]);
		assert(res == -1);
	}

	int mn = n;
	//cerr << "----DEBUG----" << '\n';
	for(int i = 0; i<n; i++) {
		mn = min(mn, ans[i]);
		//cerr << ans[i] << ' ';
	}
	//cerr << '\n';

	//cerr << "-------------" << '\n';

	vec<int> res(n);
	for(int i = 0; i<n; i++) {
		res[i] = ans[i] == mn;
	}

	return res;
}
#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...