#include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "vector"
#include "string"
#include "map"
#include "unordered_map"
#include "algorithm"
#include "functional"
#include "set"

using namespace std;

const long long int MOD = 1000000007;

long long int N, M, K, H, W, L, R;

struct Edge{
	int to;
	long long int capa;
	long long int cost;
	unsigned long long int rev_index;
};

class Min_Cost_Flow {//超頂点を忘れない
	int n;
	bool d;
	vector<vector<Edge>>edge;
	vector<long long int>potent;
	vector<long long int>dist;
	vector<int>pre_node;
	vector<int>pre_edge;
public:
	Min_Cost_Flow(int node, bool directed) {
		node += 2;
		n = node;
		if (directed)d = true;
		else d = false;
		edge.resize(n);
		potent.resize(n);
		dist.resize(n);
		pre_node.resize(n);
		pre_edge.resize(n);
		return;
	}
	void Add_Edge(int s, int g, long long int cap, long long int cost) {
		if (!d) {
			edge[s].push_back({ g,cap,cost,edge[g].size() });
			edge[g].push_back({ s,0,-cost ,edge[s].size() - 1 });
		}
		else {////Fix!Fix!Fix!!!!!!!
			edge[s].push_back({ g,cap,cost,edge[g].size() });
			edge[g].push_back({ s,cap,cost ,edge[s].size() - 1 });
		}
	}
	long long int Solve(int s, int g, long long int f) {
		long long int ret = 0;
		for(auto &i:potent)i=0;
		while (f > 0) {
		//	cout << f << endl;
			priority_queue<pair<long long int, int>, vector<pair<long long int, int>>, greater<pair<long long int, int>>>PQ;
			for (auto &i : dist)i = MOD * MOD;
			dist[s] = 0;
			PQ.push({ dist[s],s });
			while (!PQ.empty()) {
				long long int c = PQ.top().first;
				int cn = PQ.top().second;
			//	cout <<"jo"<< cn << endl;
				PQ.pop();
				if (dist[cn] < c)continue;
				int cnt = 0;
				for (auto &i : edge[cn]) {
				//	cout << i.to << endl;
				//	cout << i.capa << " " << dist[i.to] << " " << dist[cn] << " " << i.cost << " " << potent[cn] << " "<<potent[i.to] << endl;
					if (i.capa > 0 && dist[i.to] > dist[cn] + i.cost + potent[cn] - potent[i.to]) {
						dist[i.to] = dist[cn] + i.cost + potent[cn] - potent[i.to];
						pre_node[i.to] = cn;
						pre_edge[i.to] = cnt;
						PQ.push({ dist[i.to],i.to });
					}
					cnt++;
				}
			}
			if (dist[g] == MOD * MOD)return -1;
			for (int i = 0; i < n; i++) potent[i] += dist[i];
			long long int d = f;
			for (int i = g; i != s; i = pre_node[i]) {
			//	cout << i << endl;
				d = min(d, edge[pre_node[i]][pre_edge[i]].capa);
			}
			f -= d;
			ret += d * potent[g];
			for (int i = g; i != s; i = pre_node[i]) {
				auto &e = edge[pre_node[i]][pre_edge[i]];
				e.capa -= d;
				edge[i][e.rev_index].capa += d;
			}
		//	cout << ret << endl;
		}
		return ret;
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N;
	set<int>s;
	vector<pair<int, int>>v(N);
	long long int ans = 0;
	for (auto &i : v) {
		cin >> i.first >> i.second;
		ans += i.first + i.second;
		s.insert(i.first);
		s.insert(i.second);
	}
	map<int, int>m;
	int cnt = N;
	for (auto i : s) {
		m[i] = cnt;
		cnt++;
	}
	Min_Cost_Flow flow(N + s.size() + 10,false);
	for (int i = 0; i < N; i++) {
		flow.Add_Edge(i, m[v[i].first], 1, v[i].first);
		flow.Add_Edge(i, m[v[i].second], 1, v[i].second);
		flow.Add_Edge(i, cnt, 1, v[i].first + v[i].second);
		flow.Add_Edge(cnt + 1, i, 1, 0);
	}
	for (int i = N; i < cnt; i++)flow.Add_Edge(i, cnt + 2, 1, 0);
	flow.Add_Edge(cnt, cnt + 2, N, 0);
	cout << ans - flow.Solve(cnt + 1, cnt + 2, N) << endl;
	return 0;
}


Measured memory_bytes: 3908