#include #include #include #include #include #include #include #include using namespace std; using ll = long long; #define umap unordered_map #define uset unordered_set #define int ll namespace std { template struct hash> { size_t operator()(const pair &a) const { return std::hash()(a.first) ^ (std::hash()(a.second) << 10); } }; } struct State { pair node; uset> seen; ll dist; bool operator < (const State & other) const { return dist > other.dist; } }; signed main() { int cunt = 0; cin >> cunt; pair c; uset> nodes; map> positions; for (int i = 0; i < cunt; ++i) { cin >> c.first; cin >> c.second; nodes.insert(c); positions[c.first].push_back(c.second); } for (auto & position : positions) { sort(position.second.begin(), position.second.end()); } auto run = [&](pair begin) -> ll { priority_queue q; q.push({ begin, { begin }, 0 }); while (!q.empty()) { State s = q.top(); q.pop(); if (s.seen.size() == nodes.size()) { return s.dist; } bool seenAll = true; for (auto neighbour : positions[s.node.first]) { pair c = { s.node.first, neighbour }; if (s.seen.count(c)) continue; seenAll = false; uset> nseen = s.seen; nseen.insert(c); State ns = { c, nseen, s.dist + abs(c.first - s.node.first) + abs(c.second - s.node.second) }; q.push(ns); } if (seenAll) { auto nextLevel = positions.upper_bound(s.node.first); if (nextLevel == positions.end()) continue; for (auto neighbour : nextLevel->second) { pair c = { nextLevel->first, neighbour }; if (s.seen.count(c)) continue; seenAll = false; uset> nseen = s.seen; nseen.insert(c); State ns = { c, nseen, s.dist + abs(c.first - s.node.first) + abs(c.second - s.node.second) }; q.push(ns); } } } return -1; }; ll sx = positions.begin()->first; pair sa = { sx, positions[sx].front() }; pair sb = { sx, positions[sx].back() }; ll correct = min(run(sa), run(sb)); if (correct == -1) { goto ret; } cout << correct << endl; ret: return 0; }