이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
#define ST first
#define ND second
#define PB push_back
using namespace std;
using ll = long long;
using pi = pair<int,int>;
using vi = vector<int>;
const int nax = 200 * 1000 + 10;
int n, m;
vector<pi>V[nax];
int par[nax];
set<int>reach[nax];
int p[nax], deg[nax];
vi vertices[nax];
bool done[nax];
map<int, vi> graph[nax];
vi edges[nax];
int p2[nax], siz[nax];
int Fund(int x) {
if(p2[x] != x) p2[x] = Fund(p2[x]);
return p2[x];
}
bool Onion(int a, int b) {
a = Fund(a); b = Fund(b);
if(a == b) return false;
if(siz[a] < siz[b]) swap(a, b);
p2[b] = a;
siz[a] += siz[b];
return true;
}
void merge(int a, int b) {
if(p[a] == p[b]) return;
if((int)vertices[p[a]].size() < (int)vertices[p[b]].size()) swap(a, b);
int pb = p[b];
for(auto &it : graph[pb]) {
if(reach[p[a]].count(it.ST)) {
for(int &x : it.ND) {
edges[p[a]].PB(x);
}
} else {
for(int &x : it.ND) {
graph[p[a]][it.ST].PB(x);
}
}
}
graph[pb].clear();
for(int x : vertices[pb]) {
p[x] = p[a];
vertices[p[a]].PB(x);
}
for(int x : reach[pb]) {
if(!reach[p[a]].count(x)) {
for(int &y : graph[p[a]][x]) {
edges[p[a]].PB(y);
}
graph[p[a]][x].clear();
}
reach[p[a]].insert(x);
}
vertices[pb].clear();
reach[pb].clear();
}
vi find_reachable(vi r, vi u, vi v, vi c) {
n = (int)r.size();
m = (int)u.size();
for(int i = 0; i < m; ++i) {
V[u[i]].emplace_back(v[i], c[i]);
V[v[i]].emplace_back(u[i], c[i]);
}
vi tmp = {};
for(int i = 0; i < n; ++i) {
p2[i] = i; siz[i] = 1;
bool any = false;
for(auto nbh : V[i]) {
if(r[i] == nbh.ND) {
par[i] = nbh.ST;
edges[i].PB(nbh.ST);
any = true;
}
graph[i][nbh.ND].PB(nbh.ST);
}
if(!any) {
tmp.PB(i);
}
reach[i].insert(r[i]);
vertices[i].PB(i);
p[i] = i;
deg[par[i]]++;
Onion(par[i], i);
}
if((int)tmp.size() > 0) {
return tmp;
}
vi zeroDeg = {};
for(int i = 0; i < n; ++i) {
if(deg[i] == 0) {
zeroDeg.PB(i);
}
}
while((int)zeroDeg.size() > 0) {
int x = zeroDeg.back();
done[x] = true;
zeroDeg.pop_back();
deg[par[x]]--;
if(deg[par[x]] == 0) zeroDeg.PB(par[x]);
}
vi roots;
for(int i = 0; i < n; ++i) {
if(!done[i]) {
vi cycle = {i};
int x = i;
done[i] = true;
while(par[x] != i) {
x = par[x];
done[x] = true;
cycle.PB(x);
}
for(int j = 1; j < (int)cycle.size(); ++j) {
merge(cycle[j - 1], cycle[j]);
}
roots.PB(p[i]);
}
}
vector<vi>res;
while((int)roots.size() > 0) {
int x = roots.back();
if(edges[x].size() == 0) {
res.PB(vertices[x]);
roots.pop_back();
continue;
}
int y = edges[x].back();
edges[x].pop_back();
if(p[x] == p[y]) continue;
x = p[x]; y = p[y];
if(!Onion(x, y)) {
vi path = {y};
while(p[par[y]] != x) {
path.PB(p[par[y]]);
y = p[par[y]];
}
path.PB(x);
for(int j = 1; j < (int)path.size(); ++j) {
merge(path[j], path[j - 1]);
}
} else {
par[x] = p[y];
roots.pop_back();
}
}
int mi = 1000000000;
for(auto &vec : res) {
mi = min(mi, (int)vec.size());
}
vi ans(n);
for(auto &vec : res) {
if((int)vec.size() == mi) {
for(int x : vec) {
ans[x] = true;
}
}
}
return ans;
}
//int main() {
//ios_base::sync_with_stdio(0);
//cin.tie(0);
//int N, M;
//cin >> N >> M;
//vi r(N), u(M), v(M), c(M);
//for(int i = 0; i < N; ++i) {
//cin >> r[i];
//}
//for(int i = 0; i < M; ++i) {
//cin >> u[i] >> v[i] >> c[i];
//}
//auto ans = find_reachable(r,u,v,c);
//for(int x : ans) cout << x << " ";
//}
# | 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... |