#include #include #include #include #include #include #include #include #include #include // Just for clean code sake, This is doable without structs or classes typedef double Distance; struct Junction; struct Cluster { std::vector members{}; }; struct Junction { int64_t x, y, z; Cluster *parentCluster = nullptr; }; Distance distanceBetween(Junction first, Junction second) { return std::sqrt(std::pow(second.x - first.x, 2) + std::pow(second.y - first.y, 2) + std::pow(second.z - first.z, 2)); } int main() { std::fstream input("input"); std::string currentLine = ""; std::vector junctionList{}; std::list clusterList{}; std::multimap> junctionDistanceMap{}; std::pair *lastPair; uint64_t junctionListSize = 0; // I do think we could process text and do the necessary calculations for the // solution, but once again, code should be preferably legiable while (std::getline(input, currentLine, '\n')) { uint16_t positionOfFirstComma, positionOfSecondComma; positionOfFirstComma = currentLine.find(','); positionOfSecondComma = currentLine.find(',', positionOfFirstComma + 1); int64_t x, y, z; x = std::stoll(currentLine.substr(0, positionOfFirstComma)); y = std::stoll( currentLine.substr(positionOfFirstComma + 1, positionOfSecondComma - positionOfFirstComma)); z = std::stoll(currentLine.substr(positionOfSecondComma + 1)); junctionList.push_back({x, y, z}); } // This is O(n²), ouch. It can be estimated with T_n, So idk maybe O(T_n) uint64_t count = 0; junctionListSize = junctionList.size(); for (Junction &junction : junctionList) { for (uint64_t index = ++count; index < junctionListSize; index++) { junctionDistanceMap.insert( {distanceBetween(junction, junctionList[index]), {&junction, &junctionList[index]}}); } } // Ordered by smallest to largest key count = junctionDistanceMap.size(); for (auto &Key : junctionDistanceMap) { // Just need to know when we connect every junction Junction *previousJunction = nullptr; bool isFullyConnected = true; for (Junction &junction : junctionList) { if (previousJunction == nullptr) { previousJunction = &junction; continue; } if (previousJunction->parentCluster == nullptr || previousJunction->parentCluster != junction.parentCluster) { isFullyConnected = false; break; } } if (count == 0 || isFullyConnected) { break; } count--; lastPair = &Key.second; Junction *first = Key.second.first, *second = Key.second.second; Cluster *firstCluster = first->parentCluster, *secondCluster = second->parentCluster; // 4 real possibilities bool firstHasACluster = firstCluster != nullptr, secondHasACluster = secondCluster != nullptr; // Both have clusters, merge clusters if (firstHasACluster && secondHasACluster) { // Since both are already connected if (firstCluster == secondCluster) { continue; } // This bad boy merges the clusters and updates the pointers firstCluster->members.insert(firstCluster->members.end(), secondCluster->members.begin(), secondCluster->members.end()); for (Junction *clusterJunction : secondCluster->members) { clusterJunction->parentCluster = firstCluster; } // Temp fix secondCluster->members.clear(); second->parentCluster = firstCluster; continue; } // Both don't have clusters, pair up if (!firstHasACluster && !secondHasACluster) { clusterList.push_back({{first, second}}); // Directly writing, can't use the variable here first->parentCluster = &clusterList.back(); second->parentCluster = &clusterList.back(); continue; } // Only first doesn't have it, append to second if (!firstHasACluster) { first->parentCluster = secondCluster; secondCluster->members.push_back(first); continue; } // Only second doesn't have it, append to first if (!secondHasACluster) { second->parentCluster = firstCluster; firstCluster->members.push_back(second); continue; } } std::cout << lastPair->first->x * lastPair->second->x << "\n"; }