| # | Time | Username | Problem | Language | Result | Execution time | Memory |
|---|---|---|---|---|---|---|---|
| 1303404 | chaitanyamehta | Towers (NOI22_towers) | C++20 | 0 ms | 0 KiB |
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct Edge {
int v, id;
};
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
vector<int> x(n), y(n);
for (int i = 0; i < n; ++i) cin >> x[i] >> y[i];
// compress coordinates
vector<int> xs = x, ys = y;
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end());
sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
int nx = (int)xs.size();
int ny = (int)ys.size();
int V = nx + ny;
vector<int> cx(n), cy(n);
for (int i = 0; i < n; ++i) {
cx[i] = int(lower_bound(xs.begin(), xs.end(), x[i]) - xs.begin());
cy[i] = int(lower_bound(ys.begin(), ys.end(), y[i]) - ys.begin()) + nx;
}
// adjacency
vector<vector<Edge>> g(V);
for (int i = 0; i < n; ++i) {
g[cx[i]].push_back({cy[i], i});
g[cy[i]].push_back({cx[i], i});
}
// arrays sized properly
vector<int> vis(V, 0);
vector<int> par_edge(V, -1); // par_edge[node] = edge id used to reach node in DFS tree
vector<int> used(n, 0);
vector<int> deg(V, 0);
// ITERATIVE DFS1 to build spanning forest and par_edge
for (int start = 0; start < V; ++start) {
if (vis[start]) continue;
// stack of nodes for DFS
stack<int> st;
st.push(start);
vis[start] = 1;
par_edge[start] = -1;
while (!st.empty()) {
int u = st.top(); st.pop();
for (const Edge &e : g[u]) {
int v = e.v;
if (vis[v]) continue;
vis[v] = 1;
par_edge[v] = e.id; // edge id that connects v with its parent u
st.push(v);
}
}
}
// Select cycle edges (edges that are not par_edge[any endpoint])
for (int i = 0; i < n; ++i) {
int u = cx[i], v = cy[i];
if (par_edge[u] != i && par_edge[v] != i) { // non-tree edge
if (deg[u] < 2 && deg[v] < 2) {
used[i] = 1;
deg[u]++; deg[v]++;
}
}
}
// Prepare children lists for tree edges so we can get a postorder deterministically
vector<vector<pair<int,int>>> children(V); // children[u] = list of (child, edge_id)
for (int u = 0; u < V; ++u) {
for (const Edge &e : g[u]) {
int v = e.v;
if (par_edge[v] == e.id) {
// e.id is the tree-edge that reaches v from u (u is parent of v)
children[u].push_back({v, e.id});
}
}
}
// Iterative postorder traversal using explicit stack (no recursion)
vector<int> visited2(V, 0);
vector<int> postorder_nodes; // store nodes in postorder
for (int root = 0; root < V; ++root) {
if (visited2[root]) continue;
// stack of pairs (node, state) where state==0 means first time, state==1 means children processed
vector<pair<int,int>> st;
st.emplace_back(root, 0);
while (!st.empty()) {
auto [u, state] = st.back();
st.pop_back();
if (state == 0) {
if (visited2[u]) continue;
visited2[u] = 1;
st.emplace_back(u, 1); // will add to postorder after children
// push children
for (auto &p : children[u]) {
int v = p.first;
if (!visited2[v]) st.emplace_back(v, 0);
}
} else {
postorder_nodes.push_back(u);
}
}
}
// Process edges in postorder: when we process node u, we will visit its children and handle edge (u->child)
// We need mapping from child->edge id; children[u] has that.
// Because postorder_nodes is nodes (parents after children), we iterate parents in that order
for (int u : postorder_nodes) {
for (auto &p : children[u]) {
int v = p.first;
int eid = p.second;
if (!used[eid] && deg[u] < 2 && deg[v] < 2) {
used[eid] = 1;
deg[u]++; deg[v]++;
}
}
}
// Output
for (int i = 0; i < n; ++i) cout << used[i];
cout << '\n';
return 0;
}
