Problem:
Score : 700 points

Problem Statement

We have a directed weighted graph with N vertices.
Each vertex has two integers written on it, and the integers written on Vertex i are A_i and B_i.

In this graph, there is an edge from Vertex x to Vertex y for all pairs 1 \leq x,y \leq N, and its weight is {\rm min}(A_x,B_y).

We will consider a directed cycle in this graph that visits every vertex exactly once.
Find the minimum total weight of the edges in such a cycle.

Constraints

2 \leq N \leq 10^5

1 \leq A_i \leq 10^9

1 \leq B_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 B_1
A_2 B_2
:
A_N B_N

Output

Print the minimum total weight of the edges in such a cycle.

Sample Input 1

3
1 5
4 2
6 3

Sample Output 1

7

Consider the cycle 1→3→2→1. The weights of those edges are {\rm min}(A_1,B_3)=1, {\rm min}(A_3,B_2)=2 and {\rm min}(A_2,B_1)=4, for a total of 7.
As there is no cycle with a total weight of less than 7, the answer is 7.

Sample Input 2

4
1 5
2 6
3 7
4 8

Sample Output 2

10

Sample Input 3

6
19 92
64 64
78 48
57 33
73 6
95 73

Sample Output 3

227

Solution in Rust (1.15.1) (judge verdict: Wrong Answer)

#[allow(unused_imports)]
use std::cmp::{min,max};
#[allow(unused_imports)]
use std::collections::{BTreeMap,BTreeSet};
#[allow(unused_imports)]
use std::ops::*;
#[allow(unused_imports)]
use std::collections::BinaryHeap;

#[allow(unused_macros)]
macro_rules! ite {
    ($c:expr, $t:expr, $f:expr) => {{
        if $c { $t } else { $f }
    }};
}

use std::io::BufRead;
use std::io;
use std::str;

// ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
// diff: using Parser
#[macro_export]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut parser = Parser::new(reader);
        input_inner!{parser, $($r)*}
    };
}

#[macro_export]
macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

#[macro_export]
macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

fn gcd(n: usize, m: usize) -> usize {
    ite!(m == 0, n, gcd(m, n%m))
}

fn main() {
    input! {
        n: usize,
        xys: [(i64,i64); n],
    };
    let res1 = {
        let mut xs: Vec<(i64, usize)> = xys.iter().enumerate().map(|(i,&(x,_))| (x,i)).collect();
        let ys: Vec<(i64, usize)> = xys.iter().enumerate().map(|(i,&(_,y))| (y,i)).collect();
        let mut heap = BinaryHeap::from(ys);
        xs.sort();
        xs.reverse();
        let mut res = 0;
        let mut dset = DisjointSet::new(n);
        for i in 0..n-2 {
            let (x,i) = xs[i];
            let (y1,k1) = heap.pop().unwrap();
            if i != k1 && !dset.same(i, k1) {
                res += min(x, y1);
                dset.unite(i, k1);
            }
            else {
                {
                    let (y2,k2) = heap.pop().unwrap();
                    assert!(i != k2 && !dset.same(i, k2));
                    res += min(x, y2);
                    dset.unite(i, k2);
                }
                heap.push((y1,k1));
            }
        }
        let (y1,k1) = heap.pop().unwrap();
        let (y2,k2) = heap.pop().unwrap();
        if xs[n-2].1 != k1 && xs[n-1].1 != k2 && !dset.same(xs[n-2].1, k1) {
            res += min(xs[n-2].0, y1);
            res += min(xs[n-1].0, y2);
        }
        else {
            assert!(xs[n-2].1 != k2 && xs[n-1].1 != k1 && !dset.same(xs[n-2].1, k2));
            res += min(xs[n-2].0, y2);
            res += min(xs[n-1].0, y1);
        }
        res
    };
    let res2 = {
        let mut xs: Vec<(i64, usize)> = xys.iter().enumerate().map(|(i,&(x,_))| (x,i)).collect();
        let ys: Vec<(i64, usize)> = xys.iter().enumerate().map(|(i,&(_,y))| (-y,i)).collect();
        let mut heap = BinaryHeap::from(ys);
        xs.sort();
        xs.reverse();
        let mut res = 0;
        let mut dset = DisjointSet::new(n);
        for i in 0..n-2 {
            let (x,i) = xs[i];
            let (y1,k1) = heap.pop().unwrap();
            if i != k1 && !dset.same(i, k1) {
                res += min(x, -y1);
                dset.unite(i, k1);
            }
            else {
                {
                    let (y2,k2) = heap.pop().unwrap();
                    assert!(i != k2 && !dset.same(i, k2));
                    res += min(x, -y2);
                    dset.unite(i, k2);
                }
                heap.push((y1,k1));
            }
        }
        let (y1,k1) = heap.pop().unwrap();
        let (y2,k2) = heap.pop().unwrap();
        if xs[n-2].1 != k1 && xs[n-1].1 != k2 && !dset.same(xs[n-2].1, k1) {
            res += min(xs[n-2].0, -y1);
            res += min(xs[n-1].0, -y2);
        }
        else {
            assert!(xs[n-2].1 != k2 && xs[n-1].1 != k1 && !dset.same(xs[n-2].1, k2));
            res += min(xs[n-2].0, -y2);
            res += min(xs[n-1].0, -y1);
        }
        res
    };
    println!("{}", min(res1, res2));
}


struct DisjointSet {
    ps: Vec<Option<usize>>,
    ns: Vec<i64>,
}

impl DisjointSet {
    fn new(n: usize) -> DisjointSet {
        DisjointSet { ps: vec![None; n], ns: vec![1; n] }
    }

    fn unite(&mut self, x: usize, y: usize) {
        let nx = self.find(x);
        let ny = self.find(y);
        if nx == ny {
            return;
        }
        let (a,b) = if self.ns[nx] < self.ns[ny] { (nx,ny) } else { (ny,nx) };
        self.ps[a] = Some(b);
        self.ns[b] += self.ns[a];
    }

    fn find(&mut self, x: usize) -> usize {
        match self.ps[x] {
            Some(y) => {
                let res = self.find(y);
                self.ps[x] = Some(res);
                res
            },
            None => {
                x
            },
        }
    }

    fn same(&mut self, x: usize, y: usize) -> bool {
        self.find(x) == self.find(y)
    }
}

// ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
// ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
// diff: using std::io::BufRead::fill_buf()
pub struct Parser<R> {
    reader: R,
    buf: Vec<u8>,
    pos: usize,
}

impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}

impl<R:BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len,complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                (len, buf2[len-1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T:str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return str::from_utf8(&self.buf[begin..end]).unwrap().parse::<T>();
            }
            else {
                self.update_buf();
            }
        }
    }
}


use std::fmt::Display;
#[allow(dead_code)]
fn write_vec<T: Display>(xs: &Vec<T>) {
    if xs.len() == 0 {
        println!();
        return;
    }
    print!("{}", xs[0]);
    for i in 1..xs.len() {
        print!(" {}", xs[i]);
    }
    println!();
}