#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h> // uint64_t

// > 11*2
#define BUF_SIZE 30

// size: specify sizeof(str)
int get_str(char *str, int size) {
    if(!fgets(str, size, stdin)) return -1;
    return 0;
}

int get_int(void) {
  int num;
#ifdef BUF_SIZE
  char line[BUF_SIZE];
  if(!fgets(line, BUF_SIZE, stdin)) return 0;
  sscanf(line, "%d", &num);
#else
#error
#endif
  return num;
}

int get_int2(int *a1, int *a2) {
#ifdef BUF_SIZE
  char line[BUF_SIZE];
  if(!fgets(line, BUF_SIZE, stdin)) return -1;
  sscanf(line, "%d %d", a1, a2);
#else
#error
#endif
  return 0;
}

#define CITIES_MAX 100000
#define EDGES_MAX (CITIES_MAX*2)

struct point2d {
    int x;
    int y;
};

struct city {
    int idx;
    int feature;
};

int asc_city(const void *a1, const void *a2) {
    struct city *c1 = (struct city*)a1;
    struct city *c2 = (struct city*)a2;
    return c1->feature - c2->feature;
}

struct edge {
    int v1;
    int v2;
    int cost;
};

int asc_edge(const void *a1, const void *a2) {
    struct edge *e1 = (struct edge*)a1;
    struct edge *e2 = (struct edge*)a2;
    return e1->cost - e2->cost;
}

// union find data structure
struct ufind {
    int parent;
    int depth;
};

struct ufind *create_union_find() {
    static struct ufind ufind[EDGES_MAX];
    int i;
    for(i = 0; i < EDGES_MAX; i++) {
        ufind[i].parent = i;
        ufind[i].depth = 1;
    }
    return ufind;
}

int get_root(struct ufind *ufind, int idx) {
    struct ufind *v = &ufind[idx];
    int base = idx;
    while(base != v->parent) {
        base = v->parent;
        v = &ufind[base];
    }
    return base;
}

int is_same(struct ufind *ufind, int v1, int v2) {
    return get_root(ufind, v1) == get_root(ufind, v2);
}

void _connect(struct ufind *ufind, int v1, int v2) {
    int b1 = get_root(ufind, v1);
    int b2 = get_root(ufind, v2);
    struct ufind *root1 = &ufind[b1];
    struct ufind *root2 = &ufind[b2];
    if(root1->depth >= root2->depth) {
        if(root1->depth == root2->depth) root1->depth++;
        root2->depth = root1->depth;
        root2->parent = b1;
    } else {
        root1->depth = root2->depth;
        root1->parent = b2;
    }
    return;
}

int main(void) {
    int cs = get_int();
    static struct city xys[2][CITIES_MAX];
    static struct edge edges[EDGES_MAX];
    int eidx = 0;
    int i, k;
    for(i = 0; i < cs; i++) {
        int x, y;
        get_int2(&x, &y);
        xys[0][i] = (struct city){i, x};
        xys[1][i] = (struct city){i, y};
    }
    // x and y coordinates are independent.
    qsort(xys[0], cs, sizeof(struct city), asc_city);
    qsort(xys[1], cs, sizeof(struct city), asc_city);

    for(k = 0; k < 2; k++) {
        struct city *ks = xys[k];
        for(i = 1; i < cs; i++) {
            int idx1 = ks[i-1].idx;
            int idx2 = ks[i].idx;
            // ensure that cost >= 0
            int cost = ks[i].feature - ks[i-1].feature;
            struct edge e = {idx1, idx2, cost};
#ifdef DEBUG
            printf("(%d, %d) -> %d\n", idx1, idx2, cost);
#endif
            edges[eidx++] = e;
        }
    }
    qsort(edges, eidx, sizeof(struct edge), asc_edge);
    struct ufind *ufind = create_union_find();

    // Kruskal algorithm (< 200000)
    uint64_t ans = 0;
    for(i = 0; i < eidx; i++) {
        int v1 = edges[i].v1;
        int v2 = edges[i].v2;
        // if the edge between v1 and v2 are connected, it ensures connectedness.
        if(!is_same(ufind, v1, v2)) {
            _connect(ufind, v1, v2);
            ans += (uint64_t)edges[i].cost;
        }
    }
    printf("%llu\n", ans);
    return 0;
}

Measured memory_bytes: 7404