#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <cfloat>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <numeric>
#include <iterator>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef istringstream ISS;
typedef ostringstream OSS;

#define REP( i, m, n ) for ( int i = (int)( m ); i < (int)( n ); ++i )
#define FOR( v, c ) for ( auto &v : c )
#define EACH( it, c ) for ( auto it = c.begin(); it != c.end(); ++it )
#define ALL( c ) (c).begin(), (c).end()
#define DRANGE( c, p ) (c).begin(), (c).begin() + p, (c).end()

#define PB( n ) push_back( n )
#define MP( a, b ) make_pair( ( a ), ( b ) )
#define EXIST( c, e ) ( (c).find( e ) != (c).end() )

#define fst first
#define snd second

#define DUMP( x ) cerr << #x << " = " << ( x ) << endl
#define DEBUG( x ) cerr << __FILE__ << ":" << __LINE__ << ": " << #x << " = " << ( x ) << endl

// 最小費用流 O( F |E| log |V| )
class MinimumCostFlow
{
private:
	struct Edge
	{
		int to, cap, cost, rev;
		Edge( int t, int c, int d, int r ) : to( t ), cap( c ), cost( d ), rev( r ) {}
	};

	const int V;
	vector< vector<Edge> > G;

public:
	MinimumCostFlow( int v ) : V( v ), G( V ) {};

	void connect( int from, int to, int cap, int cost )
	{
		G[ from ].PB( Edge( to, cap, cost, G[ to ].size() ) );
		G[ to ].PB( Edge( from, 0, -cost, G[ from ].size() - 1 ) );
		return;
	}

	int solve( int s, int t, int f )
	{
		int res = 0;
		vector<int> h( V, 0 ), prevv( V ), preve( V );

		while ( 0 < f )
		{
			vector<int> distance( V, INT_MAX );
			distance[s] = 0;

			priority_queue< pair<int,int>, vector< pair<int,int> >, greater< pair<int,int> > > que;
			que.push( make_pair( 0, s ) );
			
			while ( !que.empty() )
			{
				int d = que.top().first;
				int v = que.top().second;
				que.pop();

				if ( distance[v] < d )
				{
					continue;
				}

				for ( int i = 0; i < G[v].size(); ++i )
				{
					Edge &e = G[v][i];
					if ( 0 < e.cap && distance[v] + e.cost + h[v] - h[ e.to ] < distance[ e.to ] )
					{
						distance[ e.to ] = distance[v] + e.cost + h[v] - h[ e.to ];
						prevv[ e.to ] = v;
						preve[ e.to ] = i;
						que.push( make_pair( distance[ e.to ], e.to ) );
					}
				}
			}

			if ( distance[t] == INT_MAX )
			{
				return -1;
			}

			for ( int i = 0; i < V; ++i )
			{
				h[i] += distance[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[v][ e.rev ].cap += d;
			}
		}

		return res;
	}
};
// MinimumCostFlow( |V| )
// connect( from, to, cap, cost )
// solve( s, t, f )

const int INF = INT_MAX / 2;

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

	int n;
	cin >> n;

	VI as( n ), bs( n ), widthes;
	REP( i, 0, n )
	{
		cin >> as[i] >> bs[i];
		widthes.PB( as[i] );
		widthes.PB( bs[i] );
	}
	sort( ALL( widthes ) );
	widthes.erase( unique( ALL( widthes ) ), widthes.end() );
	const int W = widthes.size();

	MinimumCostFlow mcf( n + W + 3 );
	// source -> block
	REP( i, 0, n )
	{
		mcf.connect( n + W + 1, i, 1, 0 );
	}
	//  block -> width
	REP( i, 0, n )
	{
		REP( j, 0, W )
		{
			if ( as[i] == widthes[j] )
			{
				mcf.connect( i, n + j, 1, -bs[i] );
			}
			if ( bs[i] == widthes[j] )
			{
				mcf.connect( i, n + j, 1, -as[i] );
			}
		}
	}
	REP( i, 0, n )
	{
		mcf.connect( i, n + W, 1, 0 );
	}
	// widhh -> sink
	REP( i, 0, W )
	{
		mcf.connect( n + i, n + W + 2, 1, 0 );
	}
	mcf.connect( n + W, n + W + 2, INF, 0 );

	cout << mcf.solve( n + W + 1, n + W + 2, n ) * -1 << endl;

	return 0;
}

Measured memory_bytes: 1608