#include #include #include #include #include #include #include struct Vertex { int x, y; }; struct Edge { int u, v, d; }; bool operator<(const Edge& a, const Edge& b) { return std::tuple(a.d, a.u, a.v) < std::tuple(b.d, b.u, b.v); } int optimize(const std::vector& clients) { int N = clients.size(); std::vector edges; for (int u = 0; u < N; ++u) { for (int v = u + 1; v < N; ++v) { int d = std::abs(clients[u].x - clients[v].x) + std::abs(clients[u].y - clients[v].y); edges.push_back({u, v, d}); } } std::sort(edges.begin(), edges.end()); std::reverse(edges.begin(), edges.end()); std::vector> clique_members(N); std::vector opposing_clique(N, -1); std::vector client_clique(N, -1); for (auto e : edges) { //std::cerr << e.u << " " << e.v << " : " << e.d << "\n"; if (client_clique[e.u] == -1 && client_clique[e.v] == -1) { // new cliques int c = e.u; int o = e.v; clique_members[c].insert(e.u); client_clique[e.u] = c; opposing_clique[c] = o; clique_members[o].insert(e.v); client_clique[e.v] = o; opposing_clique[o] = c; } else if (client_clique[e.u] == -1) { // expand existing clique int c = opposing_clique[client_clique[e.v]]; client_clique[e.u] = c; clique_members[c].insert(e.u); } else if (client_clique[e.v] == -1) { // expand existing clique int c = opposing_clique[client_clique[e.u]]; client_clique[e.v] = c; clique_members[c].insert(e.v); } else if (client_clique[e.u] == client_clique[e.v]) { // this is the longest edge that we cannot remove return e.d; } else if (client_clique[e.u] == opposing_clique[client_clique[e.v]]) { // already in opposing cliques } else { // combine 4 existing cliques into 2 int c1 = client_clique[e.u]; int o1 = opposing_clique[c1]; int o2 = client_clique[e.v]; int c2 = opposing_clique[o2]; for (int i : clique_members[c2]) { clique_members[c1].insert(i); client_clique[i] = c1; } clique_members[c2].clear(); opposing_clique[c2] = -1; for (int i : clique_members[o2]) { clique_members[o1].insert(i); client_clique[i] = o1; } clique_members[o2].clear(); opposing_clique[o2] = -1; } } return 0; } int main(int argc, char **argv) { std::ifstream fin; if (argc >= 2) { fin.open(argv[1]); } std::istream& in = fin.is_open() ? fin : std::cin; std::vector clients; int N; in >> N; while (N--) { Vertex v; in >> v.x >> v.y; clients.push_back(v); } std::cout << optimize(clients) << "\n"; return 0; }