#include #include #include #include using namespace std; void solve(istream& in); int partition(); int main(int argc, char** argv) { if (argc > 1) { ifstream in (argv[1]); solve (in); } else { solve(cin); } return 0; } class Customer { public: int x; int y; Customer* assignedTo; Customer* opposedTo; Customer(int x0=0, int y0=0); Customer* find(); Customer* unionf(Customer* c2); }; Customer::Customer(int x0, int y0) { x = x0; y = y0; assignedTo = this; opposedTo = nullptr; } Customer* Customer::find() { Customer* signature = this; while (signature->assignedTo != signature) { signature = signature->assignedTo; } assignedTo = signature; return signature; } Customer* Customer::unionf(Customer* c2) { // cerr << " merging " << c2 << " into " << this); c2->assignedTo = find(); return this; } ostream& operator<< (ostream& out, const Customer& c) { out << "(" << c.x << "," << c.y << ")"; return out; } int nCustomers; Customer* customers; void solve(istream& in) { in >> nCustomers; customers = new Customer[nCustomers]; for (int i = 0; i < nCustomers; ++i) { int x, y; in >> x >> y; customers[i].x = x; customers[i].y = y;; } int slowest = partition(); cout << slowest << endl; } class Edge { public: Customer source; Customer dest; int dist; Edge(Customer source0=Customer(), Customer dest0=Customer()); bool operator< (const Edge& e) const { return e.dist < dist; } }; Edge::Edge(Customer source0, Customer dest0) { source = source0; dest = dest0; dist = abs(source.x - dest.x) + abs(source.y - dest.y); } ostream& operator<< (ostream& out, const Edge& e) { out << "[" << e.source << ", " << e.dest << ": " << e.dist << "]"; return out; } /** * Repeatedly process the largest remaining edges, marking the vertices * as needing to belong to a different clique. */ int partition() { int nEdges = (nCustomers)*(nCustomers-1)/2; Edge* edges = new Edge[nEdges]; int k = 0; for (int i = 0; i < nCustomers; ++i) for (int j = i+1; j < nCustomers; ++j) { edges[k] = Edge(customers[i], customers[j]); ++k; } // Sort edges into decreasing order of length sort(edges, edges+nEdges); for (int edgeNum = 0; edgeNum < nEdges; ++edgeNum) { Edge& toBeRemoved = edges[edgeNum]; // cerr << "edge is " << toBeRemoved << endl;; Customer c1 = toBeRemoved.source; Customer c2 = toBeRemoved.dest; Customer* clique1 = c1.find(); Customer* clique2 = c2.find(); // cerr << "cliques are " << clique1 << " and " << clique2 << endl; // cerr << "oppositions are " << clique1.opposedTo << " and " << clique2.opposedTo << endl; if (clique1 == clique2) { // Largest remaining edge is within a single clique. // We are done. return toBeRemoved.dist; } else { // c1 and c2 must stay in different cliques // Merge c1's clique with the opposition of c2. Customer* cba = clique2->opposedTo; if (cba == nullptr) { clique2->opposedTo = clique1; } else { clique1->unionf(cba->find()); } // Merge c2's clique with the opposition of c1. cba = clique1->opposedTo; if (cba == nullptr) { clique1->opposedTo = clique2; } else { clique2->unionf(cba->find()); } } } // We have removed all the edges (should only happen for N == 2) return 0; }