Problem:
A: Undo Swapping

問題文

$N$ 行 $N$ 列のマス目の上に $N$ 個の石が置いてあります。
$i$ 番目の石は $R_i$ 行 $C_i$ 列にあります。同じマスに複数の石が置かれていることはありません。

あなたは次の2種類の操作を任意の順で任意の回数行うことができます。

2つの行を選び、それらを交換する

2つの列を選び、それらを交換する。

$N$ 個の石を、マス目の左上から右下にかけての対角線上に並べることが出来るかを判定するプログラムを作成してください。
可能な場合は必要な最小の操作回数を出力してください。不可能な場合は $-1$ を出力してください。

ただし、対角線上に並ぶ石の順番は関係無い ことに注意してください。
例えば、1番目の石を1行1列のマスに配置する必要はありません。

制約

入力は全て整数

$1 \leq N \leq 10^5$

$1 \leq R_i, C_i \leq N$ $(1 \leq i \leq N)$

$R_i \ne R_j$ または $C_i \ne C_j$ $(i \ne j)$

入力

入力は標準入力から以下の形式で与えられます。

$N$
$R_1$ $C_1$
$R_2$ $C_2$
$\vdots$
$R_N$ $C_N$

出力

問題文中の条件を満たせる場合は、必要な最小の操作回数を一行に出力してください。
不可能である場合、$-1$ を一行に出力してください。

入出力例

入力例1

3
2 1
3 2
1 3

出力例1

2

初めに列1と列3を入れ替え、次に行2と行3を入れ替えることで達成できます。
1回の操作で条件を満たすことは出来ないため、答えは2となります。

入力例2

3
1 1
1 2
3 3

出力例2

-1

入力例3

3
1 1
2 2
3 3

出力例3

0

入力例4

5
4 1
3 5
5 4
1 2
2 3

出力例4

4

Solution in Rust (judge verdict: Accepted)

fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { stdin: s.lock() };
    let n: usize = sc.read();

    let mut x_used = vec![false; n];
    let mut y_used = vec![false; n];

    let mut px = vec![(0, 0); n];
    let mut py = vec![(0, 0); n];

    for _ in 0..n {
        let x = sc.read::<usize>() - 1;
        let y = sc.read::<usize>() - 1;
        if x_used[x] || y_used[y] {
            println!("-1");
            return;
        }
        x_used[x] = true;
        y_used[y] = true;
        px[x] = (x, y);
        py[y] = (x, y);
    }

    let mut ans = 0;
    for i in 0..n {
        let p1 = px[i];
        let p2 = py[i];
        if p1 == p2 {
            assert_eq!(p1, (i, i));
            continue;
        }
        let (x1, y1) = p1;
        let (x2, y2) = p2;
        assert_eq!(x1, i);
        assert_eq!(y2, i);
        px[i] = (i, i);
        py[i] = (i, i);

        let next = (x2, y1);
        px[x2] = next;
        py[y1] = next;

        ans += 1;
    }

    println!("{}", ans);
}

/// ..x
/// x..
/// .x.

/// x..
/// ..x
/// .x.

pub struct Scanner<R> {
    stdin: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .stdin
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}