#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <array>
#include <climits>
#include <bitset>
#include <cassert>
#include <unordered_map>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define UNIQUE(v) (v).erase(unique(ALL(v)), (v).end())
#define MP make_pair
#define MT make_tuple

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> P;

struct MinCostFlow{
	struct edge{
		int to, cost, rev, cap;
		edge(int to, int cost, int rev, int cap) :to(to), cost(cost), rev(rev), cap(cap){}
	};

	int n;
	vector<vector<edge>> G;

	void add(int from, int to, int cost, int cap){
		G[from].push_back(edge(to, cost, G[to].size(), cap));
		G[to].push_back(edge(from, -cost, G[from].size() - 1, 0));
	}
	vector<int> dist, h, prevv, preve;
	static const int INF = 1e9;

	MinCostFlow(int size){
		n = size;
		G.assign(n, vector<edge>());
		dist.assign(n, 0);
		h.assign(n, 0);
		prevv.assign(n, 0);
		preve.assign(n, 0);
	}

	void tdfs(int v, vector<int> &vis, vector<int> &ord){
		vis[v] = 1;
		for (auto e : G[v]){
			if (!e.cap) continue;
			if (vis[e.to]) continue;
			tdfs(e.to, vis, ord);
		}
		ord.push_back(v);
	}

	void tsort(vector<int> &ord){
		vector<int> vis(n);
		for (int i = 0; i < n; ++i) if (!vis[i]) tdfs(i, vis, ord);
		reverse(ord.begin(), ord.end());
	}

	void dag_mindist(int s){
		fill(h.begin(), h.end(), INF);
		h[s] = 0;
		vector<int> ord;
		tsort(ord);
		for (int i = 0; i < n; ++i){
			int v = ord[i];
			if (h[v] == INF) continue;
			for (auto e : G[v]){
				if (!e.cap) continue;
				h[e.to] = min(h[e.to], h[v] + e.cost);
			}
		}
	}

	int min_cost_flow(int s, int t, int f){
		int res = 0;
		rep(i, n) h[i] = 0;
		dag_mindist(s);
		while (f){
			rep(i, n) dist[i] = INF;
			dist[s] = 0;
			priority_queue<P, vector<P>, greater<P> > q;
			q.push(MP(0, s));
			while (!q.empty()){
				int pos = q.top().second;
				int d = q.top().first;
				q.pop();

				if (dist[pos] < d) continue;
				dist[pos] = d;

				rep(i, G[pos].size()){
					edge &e = G[pos][i];
					if (e.cap <= 0) continue;
					if (dist[pos] + e.cost + h[pos] - h[e.to] < dist[e.to]){
						dist[e.to] = dist[pos] + e.cost + h[pos] - h[e.to];
						prevv[e.to] = pos;
						preve[e.to] = i;
						q.push(MP(dist[e.to], e.to));
					}
				}

			}

			if (dist[t] == INF) return -1;

			rep(i, n) h[i] += dist[i];

			int d = f;
			for (int v = t; v != s; v = prevv[v]){
				d = min(d, G[prevv[v]][preve[v]].cap);
			}
			f -= d;
			res += d*h[t];
			for (int v = t; v != s; v = prevv[v]){
				edge &e = G[prevv[v]][preve[v]];
				e.cap -= d;
				G[e.to][e.rev].cap += d;
			}
		}

		return res;
	}
};

const int N = 1e6 + 10;
int num[N];

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(20);

	int n;
	cin >> n;
	vector<int> a(n), b(n);
	rep(i, n) cin >> a[i] >> b[i];

	vector<int> c(n * 2);
	rep(i, n) c[i] = a[i], c[i + n] = b[i];
	sort(ALL(c));
	UNIQUE(c);
	int m = c.size();

	rep(i, m) num[c[i]] = i;

	MinCostFlow mcf(n + m + 2);
	const int SRC = n + m, SNK = SRC + 1;

	rep(i, n){
		mcf.add(SRC, i, 0, 1);
		mcf.add(i, n + num[a[i]], -b[i], 1);
		mcf.add(i, n + num[b[i]], -a[i], 1);
		mcf.add(i, SNK, 0, 1);
	}

	rep(i, m){
		mcf.add(n + i, SNK, 0, 1);
	}

	cout << -mcf.min_cost_flow(SRC, SNK, n) << endl;
}

Measured memory_bytes: 4956