#include using namespace std; using ll = long long; using pll = pair; #define drep(i, cc, n) for (ll i = (cc); i <= (n); ++i) #define rep(i, n) drep(i, 0, n - 1) #define all(a) (a).begin(), (a).end() #define pb push_back #define fi first #define se second mt19937_64 rng(chrono::system_clock::now().time_since_epoch().count()); const ll MOD1000000007 = 1000000007; const ll MOD998244353 = 998244353; const ll MOD[3] = {999727999, 1070777777, 1000000007}; const ll LINF = 1LL << 60LL; const int IINF = (1 << 30) - 1; struct union_find{ vector par; vector siz; union_find(int n) : par(n), siz(n, 1){ for(int i=0; i struct edge{ int from, to; T cost; edge(){} edge(int to, T cost = 1) : from(-1), to(to), cost(cost){} edge(int from, int to, T cost) : from(from), to(to), cost(cost){} }; template struct redge{ int from, to; T cap, cost; int rev; redge(int to, T cap, T cost=(T)(1)) : from(-1), to(to), cap(cap), cost(cost){} redge(int to, T cap, T cost, int rev) : from(-1), to(to), cap(cap), cost(cost), rev(rev){} }; template using Edges = vector>; template using weighted_graph = vector>; template using tree = vector>; using unweighted_graph = vector>; template using residual_graph = vector>>; namespace delaunay { struct Point { /*** Point on the 2D-plane ***/ double x, y; Point operator + (const Point& p) const { return Point{x + p.x, y + p.y}; } Point operator - (const Point& p) const { return Point{x - p.x, y - p.y}; } Point operator * (double d) const { return Point{x * d, y * d}; } Point operator / (double d) const { return Point{x / d, y / d}; } bool operator < (const Point& p) const { return x == p.x ? y < p.y : x < p.x; } Point normal() const { return Point{y, -x}; } double norm() const { return x * x + y * y; } }; double dot(Point a, Point b) { return a.x * b.x + a.y * b.y; } double cross(Point a, Point b) { return a.x * b.y - a.y * b.x; } /*** Edge connecting two points ***/ using Edge = std::pair; Edge make_edge(size_t a, size_t b) { return Edge(std::min(a,b), std::max(a,b)); } /*** Core Implementation ***/ class DelaunayTriangulation { bool is_ccw(size_t a, size_t b, size_t c) const { return cross(P[b] - P[a], P[c] - P[a]) > 0; } struct Triangle { /*** Triangle on the 2D-plane ***/ size_t a, b, c; size_t opposite(Edge e) const { if (e.first != a and e.second != a) return a; if (e.first != b and e.second != b) return b; return c; } }; Triangle make_triangle(size_t a, size_t b, size_t c) const { /*** Make triangle where the direction 'a->b->c' is counter-clockwise ***/ if (!is_ccw(a, b, c)) std::swap(b, c); return Triangle{a, b, c}; } bool point_in_triangle(size_t tar, const Triangle& t) const { /*** Check wheter a point lies in an triangle or not ***/ if (!is_ccw(t.a, t.b, tar)) return false; if (!is_ccw(t.b, t.c, tar)) return false; if (!is_ccw(t.c, t.a, tar)) return false; return true; } private: size_t n; std::vector P; std::vector T; std::vector> CH; std::vector edge; size_t add_child_triangle(size_t k, const Triangle& t) { /*** Add a child triangle for T[k] ***/ size_t new_k = T.size(); T.push_back(t); CH.push_back(std::list()); CH[k].push_back(new_k); return new_k; } size_t add_child_triangle(size_t k1, size_t k2, const Triangle& t) { /*** Add a child triangle for T[k1] and T[k2] ***/ size_t new_k = T.size(); T.push_back(t); CH.push_back(std::list()); CH[k1].push_back(new_k); CH[k2].push_back(new_k); return new_k; } size_t find_child(size_t k, size_t tar) const { /*** Find child triangle of T[k] where P[tar] lies in ***/ for (size_t i : CH[k]) if (point_in_triangle(tar, T[i])) return i; return std::numeric_limits::max(); } private: struct EdgeHash { /*** Hash function for edges ***/ size_t operator () (const Edge& e) const { static const size_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); size_t key = ((e.first << 16) ^ e.second) ^ FIXED_RANDOM; return key ^ (key >> 16); } }; // Maps an edge to its incident triangles std::unordered_map, EdgeHash> e2t; void register_triangle(size_t k, const Triangle& t) { /*** Register a new triangle ***/ e2t[make_edge(t.a, t.b)].insert(k); e2t[make_edge(t.b, t.c)].insert(k); e2t[make_edge(t.c, t.a)].insert(k); } void unregister_triangle(size_t k, const Triangle& t) { /*** Unregister an old triangle ***/ e2t[make_edge(t.a, t.b)].erase(k); e2t[make_edge(t.b, t.c)].erase(k); e2t[make_edge(t.c, t.a)].erase(k); } private: bool is_ilegal(Edge e, size_t c, size_t tar) { /*** Check wheter an edge is ilegal or not ***/ size_t a = e.first, b = e.second; Point s1 = (P[a] + P[b]) / 2.; Point s2 = (P[b] + P[c]) / 2.; Point t1 = s1 + (P[b] - P[a]).normal(); Point t2 = s2 + (P[c] - P[b]).normal(); double d1 = cross(t2 - s2, s2 - s1); double d2 = cross(t2 - s2, t1 - s1); Point ct = s1 + (t1 - s1) * d1 / d2; double dx1 = P[a].x - ct.x; double dy1 = P[a].y - ct.y; double dx2 = P[tar].x - ct.x; double dy2 = P[tar].y - ct.y; return (dx1 * dx1 + dy1 * dy1) > (dx2 * dx2 + dy2 * dy2); } void legalize_edge(size_t piv, Edge e) { /*** Legalize an edge with pivot P[piv] ***/ if (e2t.count(e) == 0) return; if (e2t[e].size() != 2) return; size_t k1 = *e2t[e].begin(); size_t k2 = *e2t[e].rbegin(); size_t a = T[k1].opposite(e); size_t b = T[k2].opposite(e); if (is_ilegal(e, a, b)) { unregister_triangle(k1, T[k1]); unregister_triangle(k2, T[k2]); e2t.erase(e); Triangle t1 = make_triangle(e.first, a, b); Triangle t2 = make_triangle(e.second, a, b); size_t k1_ = add_child_triangle(k1, k2, t1); size_t k2_ = add_child_triangle(k1, k2, t2); register_triangle(k1_, t1); register_triangle(k2_, t2); size_t c = (piv != a ? a : b); legalize_edge(piv, make_edge(e.first, c)); legalize_edge(piv, make_edge(e.second, c)); } } void sub_division(size_t k, size_t tar) { /*** Divide triangle T[k] by P[tar] ***/ unregister_triangle(k, T[k]); Triangle t1 = make_triangle(T[k].a, T[k].b, tar); Triangle t2 = make_triangle(T[k].b, T[k].c, tar); Triangle t3 = make_triangle(T[k].c, T[k].a, tar); size_t k1 = add_child_triangle(k, t1); size_t k2 = add_child_triangle(k, t2); size_t k3 = add_child_triangle(k, t3); register_triangle(k1, t1); register_triangle(k2, t2); register_triangle(k3, t3); legalize_edge(tar, make_edge(T[k].a, T[k].b)); legalize_edge(tar, make_edge(T[k].b, T[k].c)); legalize_edge(tar, make_edge(T[k].c, T[k].a)); } void modify_convexity() { /*** Modify edges of the bounding convex hull ***/ for (size_t a=n; a<=n+2; ++a) { for (size_t b=0; b> 19)) ^ (t ^ (t >> 8))); } public: DelaunayTriangulation(const std::vector& x, const std::vector& y, uint32_t seed_ = 123456789) { n = x.size(); P = std::vector(n); for (size_t i=0; i::min(); for (size_t i=0; i id(n); std::iota(id.begin(), id.end(), size_t(0)); for (size_t i=0; i(); CH = std::vector>(); T.push_back(make_triangle(n, n+1, n+2)); CH.push_back(std::list()); register_triangle(0, T[0]); e2t = std::unordered_map, EdgeHash>(); // Main iteration for (size_t tar : id) { int miss_count = 0; double px = P[tar].x, py = P[tar].y; size_t k = 0; while (!CH[k].empty()) { size_t nxt = find_child(k, tar); if (nxt == std::numeric_limits::max()) { ++miss_count; if (miss_count >= max_miss_count) break; // P[tar] perturbates when it falls on an edge double dx = min_delta + (max_delta - min_delta) * xor128() / 0xFFFFFFFFu; double dy = min_delta + (max_delta - min_delta) * xor128() / 0xFFFFFFFFu; dx *= (xor128() % 2 == 0 ? 1 : -1); dy *= (xor128() % 2 == 0 ? 1 : -1); P[tar].x = px + dx; P[tar].y = py + dy; } else { k = nxt; } } if (CH[k].empty()) sub_division(k, tar); P[tar].x = px; P[tar].y = py; } // Modify edges of the bounding convex hull modify_convexity(); // Save the solution edge = std::vector(); for (auto it : e2t) { Edge e = it.first; if (e.first < n and e.second < n) edge.push_back(e); } } const std::vector& get_edges() { return edge; } void dump(std::ostream& os) { os << edge.size() << std::endl; for (Edge e : edge) os << e.first << " " << e.second << std::endl; } }; } void solve(){ int n, l; cin >> n >> l; vector x(n), y(n); for(int i=0; i> x[i] >> y[i]; delaunay::DelaunayTriangulation DT(x, y); DT.execute(); vector tmp_E = DT.get_edges(); vector> E; for(int i=0; i<(int)tmp_E.size(); i++){ int u = tmp_E[i].first; int v = tmp_E[i].second; int dist = abs(x[u]-x[v])+abs(y[u]-y[v]); E.pb({dist, u, v}); } sort(all(E)); union_find uf(n); tree T(n); for(auto [dist, u, v] : E){ if(!uf.same(u, v)){ uf.unite(u, v); T[u].pb(edge(v)); T[v].pb(edge(u)); } } vector ans; function dfs = [&](int v, int p){ ans.pb(v); for(edge e : T[v]) if(e.to!=p){ dfs(e.to, v); } }; dfs(0, -1); cout << n << '\n'; for(int i=0; i> T; while(T--) solve(); }