#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 150005;
const int kSize = 1 << 17;
struct Point {
int x;
int y;
int i;
};
int n, cursor;
int f[kMaxN];
int v[kMaxN][8];
Point p[kMaxN];
char buffer[kSize];
void startParser() {
cursor = 0;
fread(buffer, kSize, 1, stdin);
}
inline void advanceCursor() {
cursor++;
if (cursor == kSize) {
cursor = 0;
fread(buffer, kSize, 1, stdin);
}
}
inline void readInt(int &readTarget) {
readTarget = 0;
while (buffer[cursor] < '0' || '9' < buffer[cursor]) {
advanceCursor();
}
while ('0' <= buffer[cursor] && buffer[cursor] <= '9') {
readTarget = (readTarget << 1) + (readTarget << 3) + buffer[cursor] - '0';
advanceCursor();
}
}
int manhattanDistance(const Point &u, const Point &v) {
return abs(u.x - v.x) + abs(u.y - v.y);
}
vector <Point> getOctant(const int id, const int lo, const int hi) {
if (lo < hi) {
const int med = (lo + hi) >> 1;
vector <Point> d = getOctant(id, lo, med);
vector <Point> u = getOctant(id, med + 1, hi);
if (d.size() > 0 && u.size() > 0) {
int j = 0, best = 0;
for (int i = 0; i < d.size(); i++) {
if (d[i].x + d[i].y >= u[0].x + u[0].y) {
while (j < u.size() - 1 && u[j + 1].x + u[j + 1].y <= d[i].x + d[i].y) {
j++;
if (u[best].x - u[best].y < u[j].x - u[j].y) {
best = j;
}
}
if (v[d[i].i][id] == 0 || p[v[d[i].i][id]].x - p[v[d[i].i][id]].y < u[best].x - u[best].y) {
v[d[i].i][id] = u[best].i;
}
}
}
}
vector <Point> sorted(d.size() + u.size());
merge(d.begin(), d.end(), u.begin(), u.end(), sorted.begin(), [] (const Point &u, const Point &v) { return u.x + u.y < v.x + v.y; });
return sorted;
}
else {
if (lo == hi) return vector <Point> (1, p[lo]);
else return vector <Point> ();
}
}
void solveOctants() {
sort(p + 1, p + n + 1, [] (const Point &u, const Point &v) { return u.y < v.y; });
for (int i = 0; i < 8; i++) {
getOctant(i, 1, n);
if (i & 1) {
for (int j = 1; j <= n; j++) {
p[j].x *= -1;
}
}
else {
for (int j = 1; j <= n; j++) {
swap(p[j].x, p[j].y);
}
}
}
}
void setStart() {
srand(time(NULL));
for (int i = 1; i <= n; i++) {
f[i] = i;
}
}
int setFind(const int u) {
return (u == f[u] ? u: (f[u] = setFind(f[u])));
}
bool setMerge(const int u, const int v) {
int fu = setFind(u);
int fv = setFind(v);
if (fu != fv) {
if (rand() & 1) {
swap(fu, fv);
}
f[fu] = fv;
return true;
}
else return false;
}
vector <pair <int, int>> findEdges() {
solveOctants();
vector <pair <int, int>> mstEdges;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 8; j++) {
if (v[i][j] != 0) {
mstEdges.emplace_back(i, v[i][j]);
}
}
}
return mstEdges;
}
int64_t getMst() {
vector <pair <int, int>> mstEdges = findEdges();
sort(mstEdges.begin(), mstEdges.end(), [] (const pair <int, int> &u, const pair <int, int> &v) {
return manhattanDistance(p[u.first], p[u.second]) < manhattanDistance(p[v.first], p[v.second]); });
setStart();
int64_t mstCost = 0;
for (const pair <int, int> &e: mstEdges) {
const int u = e.first;
const int v = e.second;
if (setMerge(u, v) == true) {
mstCost += manhattanDistance(p[u], p[v]);
}
}
return mstCost;
}
int64_t bruteForceMst() {
vector <pair <int, int>> mstEdges;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
mstEdges.emplace_back(i, j);
}
}
sort(mstEdges.begin(), mstEdges.end(), [] (const pair <int, int> &u, const pair <int, int> &v) {
return manhattanDistance(p[u.first], p[u.second]) < manhattanDistance(p[v.first], p[v.second]);
});
setStart();
int64_t mstCost = 0;
for (const pair <int, int> &e: mstEdges) {
const int u = e.first;
const int v = e.second;
if (setMerge(u, v) == true) {
mstCost += manhattanDistance(p[u], p[v]);
}
}
return mstCost;
}
int main() {
freopen("metrou4.in", "r", stdin);
freopen("metrou4.out", "w", stdout);
startParser();
int testCases;
for (readInt(testCases); testCases > 0; testCases--) {
memset(v, 0, sizeof v);
readInt(n);
for (int i = 1; i <= n; i++) {
readInt(p[i].x);
readInt(p[i].y);
p[i].i = i;
}
printf("%lld\n", getMst());
}
return 0;
}