stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>

#define f first

#define s second

using namespace std;

const int N = 2e5+5;

int n, par[N], sz[N];

vector<pair<int, int>> x, y;

int find(int x)

{

	return (par[x] == x? x : par[x] = find(par[x]));

}

void Union(int x, int y)

{

	if(sz[x] < sz[y]) swap(x, y);

	sz[x] += sz[y];

	par[y] = x;

}

int main()

{

	iota(par, par+N, 0);

	fill(sz, sz+N, 1);

	cin >> n;

	for(int i=0, a, b; i<n; i++)

	{

		cin >> a >> b;

		x.push_back({a, i});

		y.push_back({b, i});

	}

	sort(x.begin(), x.end());

	sort(y.begin(), y.end());

	priority_queue<pair<int, pair<int, int>>> q;

	for(int i=0; i<n-1; i++) q.push({x[i].f-x[i+1].f, {x[i].s, x[i+1].s}}),

	q.push({y[i].f-y[i+1].f, {y[i].s, y[i+1].s}});

	int ans = 0;

	while(!q.empty())

	{

		auto t = q.top();

		int cost = -t.f;

		int u = find(t.s.f), v = find(t.s.s);

		q.pop();

		if(u == v) continue;

		Union(u, v);

		ans += cost;

	}

	cout << ans << endl;	

		

}

// Faster C++ solution for the same problem (measured speedup: 2.6441922552121437x):
#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cmath>

#include <string>

using namespace std;

typedef long long ll;

const int mod=1000000007;

const int maxn=100005;

int fa[maxn];

struct Node

{

    ll x,y,id;

}node[maxn];

struct Edge

{

    ll cost,p1,p2;

}edge[maxn*2];

int cmp1(Node a,Node b)

{

    return a.x<b.x;

}

int cmp2(Node a,Node b)

{

    return a.y<b.y;

}

int cmp3(Edge a,Edge b)

{

    return a.cost<b.cost;

}



int Find(int u)

{

    if(fa[u]==u)

        return fa[u];

    return fa[u]=Find(fa[u]);

}



int main()

{

    int n;

    scanf("%d",&n);

    for(int i=1;i<=n;i++)

    {

        scanf("%lld%lld",&node[i].x,&node[i].y);

        node[i].id=i;

        fa[i]=i;

    }

    sort(node+1,node+1+n,cmp1);

    int cnt=0;

    for(int i=2;i<=n;i++)

    {

        edge[++cnt].p1=node[i-1].id;

        edge[cnt].p2=node[i].id;

        edge[cnt].cost=node[i].x-node[i-1].x;

    }

    sort(node+1,node+1+n,cmp2);

    for(int i=2;i<=n;i++)

    {

        edge[++cnt].p1=node[i-1].id;

        edge[cnt].p2=node[i].id;

        edge[cnt].cost=node[i].y-node[i-1].y;

    }

    sort(edge+1,edge+1+cnt,cmp3);

    ll ans=0;

    int num=0;

    for(int i=1;i<=cnt;i++)

    {

        int fa_p1=Find(edge[i].p1);

        int fa_p2=Find(edge[i].p2);

        if(fa_p1==fa_p2) continue;

        else

        {

             fa[fa_p1]=fa_p2;

             num++;

             ans+=(edge[i].cost);

        }

        if(num==n-1)

            break;

    }

    printf("%lld\n",ans);

    return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define f first

#define s second

using namespace std;

const int N = 2e5+5;

int n, par[N], sz[N];

vector<pair<int, int>> x, y;

int find(int x)

{

	return (par[x] == x? x : par[x] = find(par[x]));

}

void Union(int x, int y)

{

	if(sz[x] < sz[y]) swap(x, y);

	sz[x] += sz[y];

	par[y] = x;

}

int main()

{

	iota(par, par+N, 0);

	fill(sz, sz+N, 1);

	cin >> n;

	for(int i=0, a, b; i<n; i++)

	{

		cin >> a >> b;

		x.push_back({a, i});

		y.push_back({b, i});

	}

	sort(x.begin(), x.end());

	sort(y.begin(), y.end());

	priority_queue<pair<int, pair<int, int>>> q;

	for(int i=0; i<n-1; i++) q.push({x[i].f-x[i+1].f, {x[i].s, x[i+1].s}}),

	q.push({y[i].f-y[i+1].f, {y[i].s, y[i+1].s}});

	int ans = 0;

	while(!q.empty())

	{

		auto t = q.top();

		int cost = -t.f;

		int u = find(t.s.f), v = find(t.s.s);

		q.pop();

		if(u == v) continue;

		Union(u, v);

		ans += cost;

	}

	cout << ans << endl;	

		

}

// Faster C++ solution for the same problem (measured speedup: 2.580449228899321x):
#pragma GCC optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math")

using namespace std;

#include <bits/stdc++.h>

#define rep(i,a,n) for (int i=a;i<n;i++)

#define per(i,a,n) for (int i=n-1;i>=a;i--)

#define pb(X) push_back(X)

#define x first

#define y second

#define all(x) (x).begin(), (x).end()

#define bbb 0;

#define INIT std::ios::sync_with_stdio(false);std::cin.tie(0);

typedef long long ll;

typedef vector<int> VI;

typedef vector<long long> VL;

typedef pair <int,int> P;

typedef pair <int,P> PP;

typedef pair <P,int> P2;

//ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}



const int MAXN = 100007;

 

struct UF

{

	int par[MAXN],rank[MAXN];

	

	void init(int n)

	{

		for(int i=0;i<n;i++)

		{

			par[i]=i;

			rank[i]=1;

		}

	}

	int find(int x)

	{

		if(x==par[x]) return x;

		return par[x]=find(par[x]);

	}

	void unite(int x,int y)

	{

		x=find(x);

		y=find(y);

		if(x==y) return;

		if(rank[x]<rank[y])

		{

			par[x]=y;

		}

		else

		{

			par[y]=x;

			if(rank[x]==rank[y]) rank[x]++;

		}

	}

	bool same(int x,int y)

	{

		return find(x)==find(y);

	}

};

UF uf;

vector <PP> edge;

P2 p1[MAXN];

P2 p2[MAXN];

 

int main()

{

	INIT

	int n;

	cin>>n;

	rep (i,0,n)

	{

		int a, b;

		cin >> a >> b;

		p1[i]=P2(P(a,b),i);

		p2[i]=P2(P(b,a),i);

	}

	sort(p1,p1+n);

	sort(p2,p2+n);

	for(int i=0;i+1<n;i++)

	{

		P p=p1[i].first,q=p1[i+1].first;

		int ct=min(abs(p.first-q.first),abs(p.second-q.second));

		edge.push_back(PP(ct,P(p1[i].second,p1[i+1].second)));

	}

	for(int i=0;i+1<n;i++)

	{

		P p=p2[i].first,q=p2[i+1].first;

		int ct=min(abs(p.first-q.first),abs(p.second-q.second));

		edge.push_back(PP(ct,P(p2[i].second,p2[i+1].second)));

	}

	sort(edge.begin(),edge.end());

	ll Ans=0;

	uf.init(n+2);

	for(int i=0;i<edge.size();i++)

	{

		P p=edge[i].second;

		if(!uf.same(p.first,p.second))

		{

			uf.unite(p.first,p.second);

			Ans+=edge[i].first;

		}

	}

	cout<<Ans;

	return bbb;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define f first

#define s second

using namespace std;

const int N = 2e5+5;

int n, par[N], sz[N];

vector<pair<int, int>> x, y;

int find(int x)

{

	return (par[x] == x? x : par[x] = find(par[x]));

}

void Union(int x, int y)

{

	if(sz[x] < sz[y]) swap(x, y);

	sz[x] += sz[y];

	par[y] = x;

}

int main()

{

	iota(par, par+N, 0);

	fill(sz, sz+N, 1);

	cin >> n;

	for(int i=0, a, b; i<n; i++)

	{

		cin >> a >> b;

		x.push_back({a, i});

		y.push_back({b, i});

	}

	sort(x.begin(), x.end());

	sort(y.begin(), y.end());

	priority_queue<pair<int, pair<int, int>>> q;

	for(int i=0; i<n-1; i++) q.push({x[i].f-x[i+1].f, {x[i].s, x[i+1].s}}),

	q.push({y[i].f-y[i+1].f, {y[i].s, y[i+1].s}});

	int ans = 0;

	while(!q.empty())

	{

		auto t = q.top();

		int cost = -t.f;

		int u = find(t.s.f), v = find(t.s.s);

		q.pop();

		if(u == v) continue;

		Union(u, v);

		ans += cost;

	}

	cout << ans << endl;	

		

}

// Faster C++ solution for the same problem (measured speedup: 2.6050807261673374x):
#include<bits/stdc++.h>

using namespace std;

#define ll long long



const int maxn = 1e5+5;

struct P

{

    int x,y,id;

}p[maxn];

struct Edge

{

    int u,v,w;

}e[maxn<<1];

int f[maxn];

int Find(int x)

{

    return f[x]==x?f[x]:f[x]=Find(f[x]);

}



int main()

{

    int n; cin>>n;

    int cnt=0;

    for(int i=1;i<=n;++i){

         scanf("%d%d",&p[i].x,&p[i].y);

         p[i].id=i;

    }

    sort(p+1,p+n+1,[](P a,P b){return a.x<b.x;});

    for(int i=1;i<n;++i){

        e[++cnt].u=p[i].id; e[cnt].v=p[i+1].id; e[cnt].w=p[i+1].x-p[i].x;

    }

    sort(p+1,p+n+1,[](P a,P b){return a.y<b.y;});

    for(int i=1;i<n;++i){

        e[++cnt].u=p[i].id; e[cnt].v=p[i+1].id; e[cnt].w=p[i+1].y-p[i].y;

    }

    ll ans=0;

    for(int i=1;i<=n;++i) f[i]=i;

    sort(e+1,e+cnt+1,[](Edge a,Edge b){return a.w<b.w;});

    for(int i=1;i<=cnt;++i){

        if(Find(e[i].u)!=Find(e[i].v)){

            f[Find(e[i].u)] = Find(e[i].v); ans+=e[i].w;

        }

    }

    cout<<ans<<"\n";

}
// Slower C++ solution:
#include <stdio.h>

#include <stdlib.h>

#include <vector>

#include <algorithm>

using namespace std;



typedef long long ll;

typedef pair<ll, pair<ll, ll> > pp;



vector<pp> v;

pp edge[1111111];

pair<ll, ll> x[111111], y[111111];

ll parent[111111];



ll Find(ll val)

{

	if (parent[val] == val)

		return val;

	else

		return parent[val] = Find(parent[val]);

}



int main(void)

{

    ll n, i, cnt = 0;



    scanf("%lld" ,&n);

    for (i = 1; i <= n; i++)

	{

		scanf("%lld %lld" ,&x[i].first, &y[i].first);

        x[i].second = y[i].second = i;

	}



	sort(x + 1, x + n + 1);

	sort(y + 1, y + n + 1);



    for (i = 1; i < n; i++)

	{

		edge[++cnt] = make_pair(x[i + 1].first - x[i].first, make_pair(x[i].second, x[i + 1].second));

		edge[++cnt] = make_pair(y[i + 1].first - y[i].first, make_pair(y[i].second, y[i + 1].second));

	}



	sort(edge + 1, edge + cnt + 1);



	for (i = 1; i <= n; i++)

		parent[i] = i;



    for (i = 1; v.size() < n - 1; i++)

	{

        ll a = Find(edge[i].second.first);

        ll b = Find(edge[i].second.second);



		if (a != b)

		{

            parent[b] = a;

            v.push_back(edge[i]);

		}

	}



	ll ans = 0;

	for (i = 0; i < v.size(); i++)

        ans += v[i].first;



	printf("%lld" ,ans);

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 4.8293523902396425x):
#include <stdio.h>

#include <algorithm>

using namespace std;



typedef long long ll;

typedef pair<ll, ll> PAIR;



pair<ll, PAIR> edge[222222];

PAIR x[111111], y[111111];

int parent[111111];



ll Find(ll val)

{

	if (parent[val] == val)

		return val;

	else

		return parent[val] = Find(parent[val]);

}



int main(void)

{

    ll n, i, ans = 0, cnt = 0;



    scanf("%lld" ,&n);

    for (i = 1; i <= n; i++)

	{

		scanf("%lld %lld" ,&x[i].first, &y[i].first);

        x[i].second = y[i].second = i;

	}



	sort(x + 1, x + n + 1);

	sort(y + 1, y + n + 1);



	for (i = 1; i < n; i++)

	{

		edge[++cnt] = make_pair(x[i + 1].first - x[i].first, make_pair(x[i].second, x[i + 1].second));

		edge[++cnt] = make_pair(y[i + 1].first - y[i].first, make_pair(y[i].second, y[i + 1].second));

	}



	sort(edge + 1, edge + cnt + 1);



	for (i = 1; i <= n; i++)

		parent[i] = i;



	int num = 0;

    for (i = 1; num < n - 1; i++)

	{

        ll a = Find(edge[i].second.first);

        ll b = Find(edge[i].second.second);



		if (a != b)

		{

            parent[b] = a;

            ans += edge[i].first;

            ++num;

		}

	}



	printf("%lld" ,ans);

	return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define REP(i,a,b) for(int i=(a);i<(b);i++)

#define RREP(i,a,b) for(int i=(a);i>=(b);i--)

#define pq priority_queue

#define P pair<int,int>

#define P2 pair<int,P>

#define P3 pair<int,P2>

typedef long long ll; typedef long double ld;

using namespace std;

const int INF=1e9, MOD=1e9+7, around[]={0,1,1,-1,-1,0,-1,1,0,0};

const int vx[]={1,0,-1,0}, vy[]={0,1,0,-1};

const ll LINF=1e18;

const ld PI=abs(acos(-1));



int n,x[100010],y[100010];

vector<P> vec, vec2;

vector<P> g[100010];



int main(){

	cin >> n;

	REP(i,0,n){

		int a, b; cin >> a >> b;

		vec.push_back({a, i});

		vec2.push_back({b, i});

	}

	sort(vec.begin(), vec.end());

	sort(vec2.begin(), vec2.end());

	

	

	REP(i,0,n - 1){

		g[vec[i].second].push_back({vec[i + 1].second, abs(vec[i + 1].first - vec[i].first)});

		g[vec[i + 1].second].push_back({vec[i].second, abs(vec[i + 1].first - vec[i].first)});

		g[vec2[i].second].push_back({vec2[i + 1].second, abs(vec2[i + 1].first - vec2[i].first)});

		g[vec2[i + 1].second].push_back({vec2[i].second, abs(vec2[i + 1].first - vec2[i].first)});

	}

	

	ll total = 0;

	bool used[100010] = {};

	pq<P, vector<P>, greater<P>> qu; qu.push({0, 0});

	while(!qu.empty()){

		auto p = qu.top(); qu.pop();

		

		if(used[p.second]) continue; used[p.second] = true;

		total += p.first;

		for(auto e:g[p.second]) qu.push({e.second, e.first});

	}

	

	cout << total << endl;

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.5974492690967064x):
#include <bits/stdc++.h>

typedef long long i64;

using std::cout;

using std::endl;

using std::cin;



struct UnionFind {

	std::vector<int> data;

	

	UnionFind(int n) {

		data.assign(n, -1);

	}

	

	void unite(int x, int y) {

		x = find(x); y = find(y);

		if(x == y) return;

		if(data[x] > data[y]) std::swap(x, y);

		data[x] += data[y];

		data[y] = x;

	}

	

	int find(int k) {

		if(data[k] < 0) return k;

		return data[k] = find(data[k]);

	}

	

	bool same(int x, int y) {

		return find(x) == find(y);

	}

};



int main(){

	int n; cin >> n;

	std::vector<int> x(n), y(n);

	std::vector<std::pair<int, int>> X, Y;

	std::vector<std::pair<int, std::pair<int, int>>> latte;

	for(int i = 0; i < n; i++) {

		cin >> x[i] >> y[i];

		

		X.push_back({x[i], i});

		Y.push_back({y[i], i});

	}

	sort(begin(X), end(X)); sort(begin(Y), end(Y));

	

	for(int i = 0; i < n - 1; i++) {

		latte.push_back({X[i + 1].first - X[i].first, {X[i + 1].second, X[i].second}});

		latte.push_back({Y[i + 1].first - Y[i].first, {Y[i + 1].second, Y[i].second}});

	}

	sort(begin(latte), end(latte));

	

	i64 ans = 0;

	UnionFind uf(n);

	for(int i = 0; i < latte.size(); i++) {

		if(uf.same(latte[i].second.first, latte[i].second.second)) continue;

		uf.unite(latte[i].second.first, latte[i].second.second);

		ans += latte[i].first;

	}

	

	cout << ans << endl;

	return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<ll, ll> P;



int N;

vector<P> x, y;

vector<vector<P>> graph(100001); //辺のコスト、行先の頂点

bitset<100001> bit;//各点を一度使ったかどうか



ll Prim(int start = 1){

    

    priority_queue<P, vector<P>, greater<P>> que;

    que.push(make_pair(0, start)); //頂点startから始める

    

    ll num = 0;

    while(!que.empty()){

        ll cost, next; tie(cost, next) = que.top(); que.pop();

        if(bit[next]) continue;

        bit[next] = true;

        num += cost;

        for(int i = 0; i < graph[next].size(); ++i) que.push(graph[next][i]);

    }

    

    return num;

}



int main(void){

	

	scanf("%d", &N);

	for(int i = 1; i <= N; ++i){

	    ll a, b; scanf("%lld %lld", &a, &b);

	    x.push_back(make_pair(a, i)), y.push_back(make_pair(b, i));

	}

	sort(x.begin(), x.end()), sort(y.begin(), y.end());

	

	for(int i = 0; i < x.size() - 1; ++i){

	    int t1 = x[i].second, t2 = x[i + 1].second;

	    ll c = abs(x[i].first - x[i + 1].first);

	    graph[t1].push_back(make_pair(c, t2));

	    graph[t2].push_back(make_pair(c, t1));

	}

	

	for(int i = 0; i < y.size() - 1; ++i){

	    int t1 = y[i].second, t2 = y[i + 1].second;

	    ll c = abs(y[i].first - y[i + 1].first);

	    graph[t1].push_back(make_pair(c, t2));

	    graph[t2].push_back(make_pair(c, t1));

	}

	

	printf("%lld\n", Prim());

	

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.5433806787681728x):
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef pair<ll, ll> P;

typedef tuple<ll, ll, ll> T;



int N;

vector<P> x, y;

vector<T> graph; //辺のコスト、行先の頂点



class UnionFind {

	public:

		vector<int> par, rank;

 		

		void init(int n) {

			par = vector<int>(n + 1);

			rank = vector<int>(n + 1);

			for (int i = 0; i < n; i++) par[i] = i, rank[i] = 0;

		}

		// 木の根を求める

		int root(int x) {

			return (par[x] == x) ? x : par[x] = root(par[x]);

		}

		// xとyの属する集合を併合

		void unite(int x, int y) {

			x = root(x), y = root(y);

			if (x == y)return;

 

			if (rank[x] < rank[y]) par[x] = y;

			else {

				par[y] = x;

				if (rank[x] == rank[y]) rank[x]++;

			}

		}

		// xとyが同じ集合に属するか否か

		bool same(int x, int y) {

			return root(x) == root(y);

		}

};



ll Kruscal(){

    

    UnionFind uf;

    uf.init(N);

    

    ll ans = 0;

    for(auto g : graph){

        ll x, y, c; tie(c, x, y) = g;

        

        if(uf.root(x) != uf.root(y)){

            uf.unite(x, y);

            ans += c;

        }

        

    }

    

    return ans;

}



int main(void){

	

	scanf("%d", &N);

	for(int i = 1; i <= N; ++i){

	    ll a, b; scanf("%lld %lld", &a, &b);

	    x.push_back(make_pair(a, i)), y.push_back(make_pair(b, i));

	}

	sort(x.begin(), x.end()), sort(y.begin(), y.end());

	

	for(int i = 0; i < N - 1; ++i){

	    graph.push_back(make_tuple(x[i + 1].first - x[i].first, x[i].second, x[i + 1].second));

	    graph.push_back(make_tuple(y[i + 1].first - y[i].first, y[i].second, y[i + 1].second));

	}

	sort(graph.begin(), graph.end());

	

	printf("%lld\n", Kruscal());

	

    return 0;

}
// Slower C++ solution:
#include<cstdio>

#include<iostream>

#include<cmath>

#include<algorithm>



typedef long long ll;



const ll INF=1E9+10;

const ll MAXN=1e5+10;

using namespace std;



ll par[2*MAXN]; 



struct NODE{

	ll len,a,b;

}node[2*MAXN];



struct NO{

	ll sit,order;

}x[MAXN],y[MAXN];



ll rk[MAXN];



bool cmp1(NO i,NO j){

	return i.sit<j.sit;

}

bool cmp2(NODE h,NODE k){

	return h.len<k.len;

}





ll find(ll a){//寻找根节点 

	if(rk[a]==a)	return a;

	else {

		rk[a]=find(rk[a]);

		return rk[a];

	} 

} 



ll Kruskal(ll ver,ll edge){//顶点数量、边数 

	ll tot=0,e=0;//目前的权值和已加入的边数

	

	//初始化前驱 

	for(ll i=1;i<=ver;i++){

		rk[i]=i;//最开始第i个顶点的集合是他自己 

	}

	

	for(ll i=1;i<=edge&&e<ver-1;i++){

		ll h=find(node[i].a);//a点根节点 

		ll k=find(node[i].b);//b点根节点 

		if(h!=k){//如果这两个点不在同一个集合中，说明可以加入这条边 

			tot+=node[i].len;//增加权值 

			e++;//增加边数 

			rk[h]=k; //合并这两个点到同一个集合 

		}

	}

	 

	return tot; 

}



 int main() {

 	ll n;

 	scanf("%lld",&n);

 	for(ll i=1;i<=n;i++){

 		scanf("%lld %lld",&x[i].sit,&y[i].sit);

 		x[i].order=i;

 		y[i].order=i;

	}

	sort(x+1,x+n+1,cmp1);

	sort(y+1,y+n+1,cmp1);

	 

	//一共有2*n-2条边从 1到2*n-2 

	for(ll i=1;i<n;i++){

		node[i].len=x[i+1].sit-x[i].sit;

		node[i].a=x[i+1].order;node[i].b=x[i].order;

		

		node[i+n-1].len=y[i+1].sit-y[i].sit;

		node[i+n-1].a=y[i+1].order;node[i+n-1].b=y[i].order;

	}

	

	sort(node+1,node+2*n-1,cmp2);

	

	//克鲁斯卡尔算法 

	ll ans=Kruskal(n,2*n-2);//顶点数量、边数 

	printf("%lld\n",ans);

	

 	return 0;

 }

// Faster C++ solution for the same problem (measured speedup: 5.127564174906461x):
#include<cstdio>

#include<algorithm>

#define ll long long





using namespace std;



const ll MAXN=1e5+10;



struct V{

	ll x,order;

}vx[MAXN],vy[MAXN];



struct Edge{

	int va,vb;

	ll w;

}e[2*MAXN];



int pre[MAXN];



void init(int n){

	for(int i=1;i<=n;i++){

		pre[i]=i;

	}

}



bool cmpv(V a,V b){

	return a.x<b.x;

}

bool cmpe(Edge a,Edge b){

	return a.w<b.w;

}



int find(int v){

	if(pre[v]==v){

		return v;

	}

	else {

		pre[v]=find(pre[v]);

		return pre[v];

	}

}



ll Kruskal(int ver,int edges){

	ll tot=0,ale=0;//权重和已加入的顶点数 

	init(ver);

	for(int i=1;i<=edges&&ale<ver-1;i++){

		 int h=find(e[i].va);

		 int k=find(e[i].vb);

		 if(h!=k){

		 	tot+=e[i].w;//增加权重 

		 	ale++;//增加边 

		 	pre[h]=k;//加入集合 

		 } 

	}

	return tot; 

	

}



int main(){

	int n;

	scanf("%d",&n);

	for(int i=1;i<=n;i++){

		scanf("%lld %lld",&vx[i].x,&vy[i].x);

		vx[i].order=vy[i].order=i;

	}

	sort(vx+1,vx+n+1,cmpv);

	sort(vy+1,vy+n+1,cmpv);

	for(int i=1;i<n;i++){

		e[i].w=vx[i+1].x-vx[i].x;

		e[i].va=vx[i+1].order,e[i].vb=vx[i].order;

		

		e[i+n-1].w=vy[i+1].x-vy[i].x;

		e[i+n-1].va=vy[i+1].order,e[i+n-1].vb=vy[i].order;

	}

	//对边长按权重排序 

	sort(e+1,e+2*n-1,cmpe);

	//Kruskal算法 找最小生成树 

	ll ans=Kruskal(n,2*n-2);

	printf("%lld",ans);

	return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

#define f first

#define s second

#define mp make_pair

typedef long long int ll;

const int N=1e5+5;

int n,vis[N];

pair< pair<int,int>, int >  p[N];

priority_queue < pair < int, pair<int,int> > > q;

ll ans;

int par(int x){

    return((vis[x]==-1||vis[x]==x)? x:par(vis[x]));

}

int main(){

    //cin.tie(NULL);

   // cout.tie(NULL);

    //ios_base::sync_with_stdio(false);

    memset(vis,-1,sizeof vis);

    cin>>n;

    for(int i=0;i<n;i++){

        cin>>p[i].f.f>>p[i].f.s;

        p[i].s=i;

    }

    sort(p,p+n);

    for(int i=1;i<n;i++)

        q.push( mp( -(p[i].f.f-p[i-1].f.f),mp(p[i].s,p[i-1].s)));



    for(int i=0;i<n;i++)

        swap(p[i].f.f,p[i].f.s);

    sort(p,p+n);

    for(int i=1;i<n;i++)

        q.push( mp(-(p[i].f.f-p[i-1].f.f),mp(p[i].s,p[i-1].s)));

    while(q.size()){

        pair< int, pair<int,int> > x=q.top();

        q.pop();

        //cout<<x.s.f<<" "<<vis[x.s.f]<<" "<<x.s.s<<" "<<vis[x.s.s]<<" "<<x.f<<'\n';

        vis[x.s.f]=par(x.s.f);

        vis[x.s.s]=par(x.s.s);

        if(vis[x.s.f]==vis[x.s.s])

            continue;

        ans+=-x.f;

        vis[vis[x.s.f]]=vis[x.s.s];

    }

    cout<<ans<<'\n';

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.420795845153761x):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define INF 0x3f3f3f3f



const int MOD = 1e9+7;

const int N = 200000+5;

const int dx[] = {-1,1,0,0,-1,-1,1,1};

const int dy[] = {0,0,-1,1,-1,1,-1,1};

using namespace std;

struct Edge

{

    int x,y;

    int dis;

    Edge(){}

    Edge(int x,int y,int dis):x(x),y(y),dis(dis) {}

    bool operator <(const Edge &rhs)const

    {

        return dis<rhs.dis;

    }

} edge[N];

int tot;

struct Node

{

    int x,y;

} node[N];

int fa[N];

bool cmpX(int a,int b)

{

    return node[a].x<node[b].x;

}

bool cmpY(int a,int b)

{

    return node[a].y<node[b].y;

}

int Find(int x)

{

    if(fa[x]!=x)

        return fa[x]=Find(fa[x]);

    return x;

}

int n;

int Kruskal()

{

    for(int i=1; i<=n; i++)

        fa[i]=i;

    int mst=0;

    sort(edge+1,edge+1+tot);

    for(int i=1; i<=tot; i++)

    {

        int x=Find(edge[i].x);

        int y=Find(edge[i].y);

        if(x!=y)

        {

            mst+=edge[i].dis;

            fa[x]=y;

        }

    }

    return mst;

}

int main()

{

    scanf("%d",&n);

    for(int i=1; i<=n; i++)

        scanf("%d%d",&node[i].x,&node[i].y);

    for(int i=1; i<=n; i++)

        fa[i]=i;

    sort(fa+1,fa+1+n,cmpX);

    for(int i=1; i<n; i++)

    {

        int x=fa[i];

        int y=fa[i+1];

        int dis=node[y].x-node[x].x;

        edge[++tot]=Edge(x,y,dis);

    }

    for(int i=1; i<=n; i++)

        fa[i]=i;

    sort(fa+1,fa+1+n,cmpY);

    for(int i=1; i<n; i++)

    {

        int x=fa[i];

        int y=fa[i+1];

        int dis=node[y].y-node[x].y;

        edge[++tot]=Edge(x,y,dis);

    }

    int mst=Kruskal();

    printf("%d\n",mst);

    return 0;

}