| # | Time | Username | Problem | Language | Result | Execution time | Memory |
|---|---|---|---|---|---|---|---|
| 1303401 | 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;
int id;
};
void dfs1(int u, vector<int> &vis, vector<int> &par_edge, const vector<vector<Edge>> &g) {
vis[u] = 1;
for (const Edge &e : g[u]) {
int vv = e.v;
if (e.id == par_edge[u]) continue; // skip parent edge
if (!vis[vv]) {
par_edge[vv] = e.id;
dfs1(vv, vis, par_edge, g);
}
}
}
void dfs2(int u, vector<int> &vis, vector<int> &par_edge, vector<int> &used, vector<int> °, const vector<vector<Edge>> &g) {
vis[u] = 1;
for (const Edge &e : g[u]) {
int v = e.v;
if (vis[v] || par_edge[v] != e.id) continue; // only traverse child-side tree edges
dfs2(v, vis, par_edge, used, deg, g);
if (!used[e.id] && deg[u] < 2 && deg[v] < 2) {
used[e.id] = 1;
deg[u]++; deg[v]++;
}
}
}
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];
// coordinate compression
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 sized to actual number of vertices
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 to V or n (not hard-coded large constants)
vector<int> vis(V, 0);
vector<int> par_edge(V, -1);
vector<int> deg(V, 0);
vector<int> used(n, 0);
// DFS #1: build spanning forest and fill par_edge (edge id for child)
for (int i = 0; i < V; ++i) {
if (!vis[i]) dfs1(i, vis, par_edge, g);
}
// Select cycle (non-tree) edges if they don't violate deg <= 2
for (int i = 0; i < n; ++i) {
int u = cx[i], v = cy[i];
// If the edge i is not the tree edge of either endpoint, it's a non-tree (cycle) edge
if (par_edge[u] != i && par_edge[v] != i) {
if (deg[u] < 2 && deg[v] < 2) {
used[i] = 1;
deg[u]++; deg[v]++;
}
}
}
// DFS #2 (postorder): process tree edges
fill(vis.begin(), vis.end(), 0);
for (int i = 0; i < V; ++i) {
if (!vis[i]) dfs2(i, vis, par_edge, used, deg, g);
}
// Output
for (int i = 0; i < n; ++i) cout << used[i];
cout << '\n';
return 0;
}
