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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using a2 = array<ll, 2>;
using a3 = array<ll, 3>;

bool chmin(auto& a, const auto& b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto& a, const auto& b) { return a < b ? a = b, 1 : 0; }

const ll INF = 1e18;
ll mod = 998244353;

ifstream in;
ofstream out;

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    if (argc > 2) {
        in.open(argv[1]);
        cin.rdbuf(in.rdbuf());
        out.open(argv[2]);
        cout.rdbuf(out.rdbuf());
    }

    ll n;
    cin >> n;
    vector<a2> v(n);
    set<ll> r, c;
    for (auto& x : v) {
        cin >> x[0] >> x[1];
        r.insert(x[0]);
        c.insert(x[1]);
    }
    if (r.size() == n && c.size() == n) {
        sort(v.begin(), v.end());
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            if (v[i][1] != i + 1) {
                swap(v[i][1], v[v[i][1] - 1][1]);
                i--;
                ans++;
            }
        }
        cout << ans << endl;
    } else {
        cout << -1 << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 14336
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

bool chmin(auto &a, auto b) { return a > b ? a = b, true : false; }
bool chmax(auto &a, auto b) { return a < b ? a = b, true : false; }

struct dsu {
    vector<int> P;
    dsu(int N) : P(N, -1) {}
    int leader(int u) { return P[u] < 0 ? u : leader(P[u]); }
    void merge(int u, int v) {
        u = leader(u);
        v = leader(v);
        if (u == v) return;
        if (P[u] > P[v]) swap(u, v);
        P[u] += P[v];
        P[v] = u;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N;
    cin >> N;
    vector<int> R(N), C(N);
    set<int> SR, SC;
    dsu uf(N);
    for (int i = 0; i < N; i++) {
        cin >> R[i] >> C[i];
        SR.insert(R[i]--);
        SC.insert(C[i]--);
        uf.merge(R[i], C[i]);
    }
    if (ssize(SR) < N || ssize(SC) < N) {
        cout << -1 << endl;
        return 0;
    }
    set<int> L;
    for (int i = 0; i < N; i++) L.insert(uf.leader(i));
    cout << N - ssize(L) << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 18560
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

class union_find {
public:
    union_find(int n) : par(n, -1) {}

    int root(int x) {
        return par[x] < 0 ? x : par[x] = root(par[x]);
    }

    void unite(int x, int y) {
        x = root(x), y = root(y);
        if(x == y) return;
        if(par[x] < par[y]) swap(x, y);
        par[x] += par[y];
        par[y] = x;
    }

    int size(int x) {
        return -par[root(x)];
    }

private:
    vector<int> par;
};

int main() {
    int n; cin >> n;
    vector<int> r(n), c(n);
    vector<int> ridx(n, -1), cidx(n, -1);
    for(int i = 0; i < n; ++i) {
        cin >> r[i] >> c[i];
        r[i]--, c[i]--;
        ridx[r[i]] = i, cidx[c[i]] = i;
    }

    {
        auto rs = r, cs = c;
        sort(rs.begin(), rs.end()); rs.erase(unique(rs.begin(), rs.end()), rs.end());
        sort(cs.begin(), cs.end()); cs.erase(unique(cs.begin(), cs.end()), cs.end());
        if((int)rs.size() != n || (int)cs.size() != n) {
            cout << -1 << endl;
            return 0;
        }
    }

    union_find uf(n);
    for(int i = 0; i < n; ++i) {
        uf.unite(cidx[r[i]], i);
        uf.unite(ridx[c[i]], i);
    }

    vector<bool> used(n);
    int ans = 0;
    for(int i = 0; i < n; ++i) {
        const int j = uf.root(i);
        if(used[j]) continue;
        used[j] = true;
        ans += uf.size(j) - 1;
    }

    cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 6528
final_rank: 9

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}


class UnionFind{
  public:
  vector<int> par;
  UnionFind(long long size) : par(size,-1){}
  bool unite(int x,int y){
    x = root(x),y = root(y);
    if(x == y)return false;
    if(par[y] < par[x])swap(x,y);
    par[x] += par[y];
    par[y] = x;
    return true;
  }
  bool find(int x,int y){
    return root(x) == root(y);
  }
  int root(int x){
    return par[x] < 0 ? x : par[x] = root(par[x]);
  }
  int size(int x){
    return -par[root(x)];
  }
};

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n;cin >> n;
  vi x(n),y(n);
  rep(i,0,n)cin >> x[i] >> y[i];
  rep(i,0,n)x[i]--,y[i]--;
  vi Cx(n),Cy(n);
  rep(i,0,n)Cx[x[i]]++,Cy[y[i]]++;
  if(*max_element(ALL(Cx)) != 1 || *max_element(ALL(Cy)) != 1){
    cout << -1 << endl;
    return 0;
  }
  UnionFind uf(n);
  int res = 0;
  rep(i,0,n){
    if(uf.unite(x[i],y[i]))res++;
  }
  cout << res << endl;
  

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 6452
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5;

int kr[N], kc[N], row[N], col[N];

int main() {
    int n;
    cin >> n;

    int ok = 1;
    for (int i = 1; i <= n; ++i) {
        int x, y;
        cin >> x >> y;
        kr[x]++, kc[y]++;
        if (kr[x] > 1 || kc[y] > 1) ok = 0;
        row[x] = y;
        col[y] = x;
    }

    if (!ok) return cout << -1 << '\n', 0;

    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
        if (row[i] == i) continue;

        int x = col[i], y = row[i];
        row[i] = i, col[i] = i;
        row[x] = y, col[y] = x;
        cnt++;
    }

    cout << cnt << '\n';
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 5000
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N;
    cin >> N;
    vector<int> A(N,0), B(N,0);
    vector<int> C(N);
    rep(i,0,N) {
        int S, T;
        cin >> S >> T;
        S--, T--;
        A[S]++, B[T]++;
        C[S] = T;
    }
    rep(i,0,N) {
        if (A[i] != 1 || B[i] != 1) {
            cout << -1 << endl;
            return 0;
        }
    }
    vector<bool> used(N,false);
    int COUNT = 0;
    rep(i,0,N) {
        if (!used[i]) {
            COUNT++;
            int Cur = i;
            while(1) {
                if (used[Cur]) break;
                used[Cur] = true;
                Cur = C[Cur];
            }
        }
    }
    cout << N-COUNT << endl;
}
accuracy: 1
time_ms: 30
memory_kb: 4404
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N;
    cin >> N;
    vector<int> A(N,0), B(N,0);
    vector<int> C(N);
    rep(i,0,N) {
        int S, T;
        cin >> S >> T;
        S--, T--;
        A[S]++, B[T]++;
        C[S] = T;
    }
    rep(i,0,N) {
        if (A[i] != 1 || B[i] != 1) {
            cout << -1 << endl;
            return 0;
        }
    }
    int COUNT = 0;
    rep(i,0,N) if (C[i] != i) COUNT++;
    if (COUNT == 0) cout << 0 << endl;
    else cout << COUNT - 1 << endl;
}
accuracy: 0.7407407407407407
time_ms: 30
memory_kb: 4136
final_rank: 19

code_snippet: // competitive-verifier: PROBLEM
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
/**
 * @brief 素集合データ構造
 * @details Implement (union by size) + (path compression)
 * @see https://github.com/atcoder/ac-library/blob/master/atcoder/dsu.hpp
 */
struct union_find {
    union_find() = default;
    explicit union_find(int _n) : _rank(_n), data(_n, -1) {}
    const int &operator[](std::size_t x) const { return data[x]; }
    int &operator[](std::size_t x) { return data[x]; }
    int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
    int get_root(int x) { return root(x); }
    bool is_root(int x) const { return data[x] < 0; }
    bool same(int x, int y) { return root(x) == root(y); }
    bool is_same(int x, int y) { return same(x, y); }
    int rank() { return _rank; }
    int size(int x) { return -(data[root(x)]); }
    int get_size(int x) { return size(x); }
    std::vector<int> leaders() {
        std::vector<int> res;
        for (int i = 0; i < (int)data.size(); ++i) {
            if (is_root(i)) res.emplace_back(i);
        }
        return res;
    }
    bool unite(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        --_rank;
        if (data[x] > data[y]) std::swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return true;
    }
    template <class F>
    bool unite(int x, int y, F f) {
        x = root(x), y = root(y);
        if (x != y) {
            if (data[x] > data[y]) std::swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        f(x, y);
        return x != y;
    }
  private:
    int _rank;
    std::vector<int> data;
};
int main(void) {
    int n;
    cin >> n;
    vector<pair<int, int>> a(n);
    cin >> a;
    for (auto &[x, y] : a) --x, --y;
    set<int> stx, sty;
    for (auto [x, y] : a) {
        stx.emplace(x);
        sty.emplace(y);
    }
    if (stx.size() != n || sty.size() != n) {
        co(-1);
        return 0;
    }
    union_find uf(n);
    for (auto [x, y] : a) uf.unite(x, y);
    co(n - uf.rank());
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 13644
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define ti3 tuple<int,int,int>
#define int128 __int128_t
#define pii128 pair<int128,int128>
const int inf = 1 << 30;
const ll linf = (ll)4e18 + 10;;
const db EPS = 1e-10;
const db pi = acos(-1);
template<class T> bool chmin(T& x, T y){
    if(x > y) {
        x = y;
        return true;
    } else return false;
}
template<class T> bool chmax(T& x, T y){
    if(x < y) {
        x = y;
        return true;
    } else return false;
}

// overload macro
#define CAT( A, B ) A ## B
#define SELECT( NAME, NUM ) CAT( NAME, NUM )

#define GET_COUNT( _1, _2, _3, _4, _5, _6 /* ad nauseam */, COUNT, ... ) COUNT
#define VA_SIZE( ... ) GET_COUNT( __VA_ARGS__, 6, 5, 4, 3, 2, 1 )

#define VA_SELECT( NAME, ... ) SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)

// rep(overload)
#define rep( ... ) VA_SELECT(rep, __VA_ARGS__)
#define rep2(i, n) for (int i = 0; i < int(n); i++)
#define rep3(i, a, b) for (int i = a; i < int(b); i++)
#define rep4(i, a, b, c) for (int i = a; i < int(b); i += c)

// repll(overload)
#define repll( ... ) VA_SELECT(repll, __VA_ARGS__)
#define repll2(i, n) for (ll i = 0; i < (ll)(n); i++)
#define repll3(i, a, b) for (ll i = a; i < (ll)(b); i++)
#define repll4(i, a, b, c) for (ll i = a; i < (ll)(b); i += c)

// rrep(overload)
#define rrep( ... ) VA_SELECT(rrep, __VA_ARGS__)
#define rrep2(i, n) for (int i = n - 1; i >= 0; i--)
#define rrep3(i, a, b) for (int i = (b) - 1; i >= a; i--)
#define rrep4(i, a, b, c) for (int i = (b) - 1; i >= a; i -= c)

// rrepll(overload)
#define rrepll( ... ) VA_SELECT(rrepll, __VA_ARGS__)
#define rrepll2(i, n) for (ll i = (ll)(n) - 1; i >= 0ll; i--)
#define rrepll3(i, a, b) for (ll i = (b) - 1; i >= (ll)(a); i--)
#define rrepll4(i, a, b, c) for (ll i = (b) - 1; i >= (ll)(a); i -= c)

// for_earh
#define fore(e, v) for (auto&& e : v)

// vector
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()

int N;
int to[100010];
bool used[100010];
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cin >> N;
    vector<int> x(N), y(N);
    rep (i, N) {
        cin >> x[i] >> y[i];
        to[x[i]] = y[i];
    }
    sort(all(x));
    sort(all(y));
    bool flag = true;
    rep (i, N) {
        flag &= x[i] == i + 1;
        flag &= y[i] == i + 1;
    }

    if (!flag) {
        cout << -1 << '\n';
        return 0;
    }
    int ans = 0;
    rep (i, 1, N + 1) {
        if (used[i]) continue;
        int c = i, cnt = 0;
        while (!used[c]) {
            used[c] = true;
            cnt++;
            c = to[c];
        }
        ans += cnt - 1;
    }
    cout << ans << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 4248
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    int N; cin >> N;
    vector<bool> R(N), C(N);
    vector<vector<int>> pos(N);
    for (int i = 0 ; i < N ; i++) {
        int y, x; cin >> y >> x;
        y--; x--;
        R[y] = true;
        C[x] = true;
        pos[y].push_back(i);
        pos[x].push_back(i);

    }
    for (auto r : R) if (r == false) {
        cout << -1 << endl;
        return 0;
    }
    for (auto c : C) if (c == false) {
        cout << -1 << endl;
        return 0;
    }

    vector<vector<int>> G(N);
    for (int i = 0 ; i < N ; i++) {
        assert(pos[i].size() == (int)2);
        G[pos[i][0]].push_back(pos[i][1]);
        G[pos[i][1]].push_back(pos[i][0]);
    }

    vector<bool> visited(N);
    auto dfs = [&](auto dfs, int v) -> void {
        visited[v] = true;
        for (auto x : G[v]) {
            if (not visited[x]) {
                dfs(dfs, x);
            }
        }
    };

    int ans = N;
    for (int i = 0 ; i < N ; i++) {
        if (not visited[i]) {
            ans--;
            dfs(dfs, i);
        }
    }

    cout << ans << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 18884
final_rank: 16

code_snippet: // 2022-05-30 update

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <unordered_map>
#include <string>
#include <sstream>
#include <climits>
#include <bitset>
#include <deque>
#include <cassert>
#include <list>
#include <queue>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

constexpr double PI = 3.141592653589793;
// const ll MOD = 998244353;
constexpr ll MOD = 1'000'000'007;
bool DEBUG = true;

// Vecterの中身を表示
void print(const std::vector<ll>& v)
{
	std::for_each(v.begin(), v.end(), [](int x)
		{ std::cout << x << " "; });
	std::cout << std::endl;
}

void print(const std::vector<int>& v)
{
	std::for_each(v.begin(), v.end(), [](int x)
		{ std::cout << x << " "; });
	std::cout << std::endl;
}

// 1~Nまでの総和を求める
ll sum_from_1_to_N(ll N)
{
	if (N < 1LL)
	{
		return 0;
	}

	if ((N & 1) == 0) // even
	{
		return N / 2 * (N + 1);
	}
	else // odd
	{
		return (N + 1) / 2 * N;
	}
}

// 1~Nまでの総和を求める
ll sum_from_A_to_B(ll A, ll B)
{
	return sum_from_1_to_N(B) - sum_from_1_to_N(A);
}

// a^bを求める
ll intPOW(int a, int b)
{
	ll number = 1LL;
	for (int i = 2; i <= b; i++)
	{
		number *= a;
	}
	return number;
}

// c(n, m)を求める
ll combination(ll n, ll m)
{
	ll up = 2;
	ll down = 2;
	for (int i = n; i > n - m; i--)
	{
		up *= i;
	}

	for (int i = m; i >= 2; i--)
	{
		down *= i;
	}

	return up / down;
}

// a,bの最大公約数を求める
long long GCD(long long a, long long b)
{
	if (b == 0)
		return a;
	else
		return GCD(b, a % b);
}

//最小公倍数
ll LCM(ll a, ll b)
{
	return a * b / GCD(a, b);
}

//素数判定, P->true, not_P->false
bool check_Prime(ll N)
{
	if (N == 2)
		return true;

	if (N == 1 || (N & 1) == 0)
		return false;

	for (ll i = 3; i <= sqrt(N); i += 2)
	{
		if (N % i == 0)
			return false;
	}
	return true;
}

//エラストステネス and 高速素因数分解
// prime->IsPrime[i]=i; not prime ->最小の素因数
vector<int> Eratosthenes(size_t max_number)
{
	vector<int> IsPrime(max_number + 1);

	// tableの初期化
	for (int i = 1; i < IsPrime.size(); ++i)
	{
		IsPrime[i] = i;
	}

	for (int i = 2; i <= sqrt(max_number); ++i)
	{
		for (int j = i; j <= max_number; j += i)
		{
			if (IsPrime[j] == j)
			{
				IsPrime[j] = i;
			}
		}
	}
	return IsPrime;
}


int main()
{
	int N;
	cin >> N;
	
	bool flag = true;
	vector<int> R(N),C(N),P(N);

	for (int i = 0; i < N; ++i)
	{
		int r, c;
		cin >> r >> c;
		--r;
		--c;
		R[r]++;
		C[c]++;
		P[r] = c;

		if (R[r] > 1 || C[c] > 1)
		{
			flag = false;
		}
	}

	if (flag == false)
	{
		puts("-1");
		return 0;
	}

	int cnt = 0;
	for (int i = 0; i < N; ++i)
	{
		if (P[i] == i)
		{
			continue;
		}
		
		for (int j = i + 1; j < N; ++j)
		{
			if (P[j] == i)
			{
				swap(P[i], P[j]);
				cnt++;
			}
		}
	}
	cout << cnt << endl;
}
accuracy: 1
time_ms: 3230
memory_kb: 4320
final_rank: 17

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    vector<int> r(n),c(n);
    vector<int> rr(n,-1),cc(n,-1);
    for(int i=0;i<n;i++){
        cin >> r[i] >> c[i];
        r[i]--; c[i]--;
        if(rr[r[i]] != -1 or cc[c[i]] != -1){
            cout << -1 << endl;
            return 0;
        }
        rr[r[i]] = i;
        cc[c[i]] = i;
    }
    int res = 0;
    for(int i=0;i<n;i++){
        int j = rr[i];
        if(r[j] == c[j]) continue;
        int k = cc[i];
        res++;
        swap(c[j],c[k]);
        cc[c[j]] = j;
        cc[c[k]] = k;
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 4568
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;



int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<pair<int, int>> A(N);
    vector<int> row(N), col(N), P(N);
    for(auto& [x, y] : A){
        cin >> x >> y;
        x--; y--;
        if(row[x]++ || col[y]++){
            cout << -1 << endl;
            return 0;
        }
        P[x] = y;
    }
    int ans = N;
    vector<bool> visit(N);
    for(int i = 0; i < N; i++) if(!visit[i]){
        ans--;
        while(!visit[i]){
            visit[i] = 1;
            i = P[i];
        }
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 5156
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1000000007;
using P=pair<ll,ll>;
const ll inf = 1ll<<60;
int main() {
    ll n;
    cin >> n;
    vector<P>mp(n);
    vector<ll>py(n);
    for(ll i=0;i<n;i++){
        cin >> mp[i].first >> mp[i].second;
        mp[i].first--;mp[i].second--;
    }
    sort(mp.begin(),mp.end());
    vector<ll>x(n,0),y(n,0);
    bool judge=false;
    for(ll i=0;i<n;i++){
        if(x[mp[i].first]>0||y[mp[i].second]>0) {
            judge=true;
        }
        x[mp[i].first]++;
        y[mp[i].second]++;
        py[mp[i].second]=i;
    }
    if(judge){
        cout << -1 << endl;
    }else{
        ll ans=0;
        for(ll i=0;i<n;i++){
            if(mp[i].first!=mp[i].second){
                ans++;
                ll posy=py[i];
                swap(py[i],py[mp[i].second]);
                swap(mp[i].second,mp[posy].second);
            }
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 30
memory_kb: 6880
final_rank: 10

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

// const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
// const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

const std::vector<int> dy = {-1, 0, 1, 0};
const std::vector<int> dx = {0, 1, 0, -1};

}  // namespace ebi

namespace ebi {

template <class T>
struct FenwickTree {
   private:
    int n;
    std::vector<T> data;

   public:
    FenwickTree(int _n) : n(_n), data(std::vector<T>(_n + 1, T(0))) {}

    void add(int i, T val) {
        i++;
        for (int x = i; x <= n; x += x & -x) {
            data[x] += val;
        }
    }

    T prefix_sum(int i) {
        assert(0 <= i && i <= n);
        T ret = 0;
        for (int x = i; x > 0; x -= x & -x) {
            ret += data[x];
        }
        return ret;
    }

    T sum(int l, int r) { return prefix_sum(r) - prefix_sum(l); }

    // prefix_sum(x) >= key となる最小のxを返す関数 O(log N)

    int lower_bound(T key) {
        if (key <= 0) return 0;
        int x = 0;
        int max = 1;
        while ((max << 1) <= n) max <<= 1;
        for (int k = max; k > 0; k >>= 1) {
            if (x + k <= n && data[x + k] < key) {
                x += k;
                key -= data[x];
            }
        }
        return x + 1;
    }
};

}  // namespace ebi

namespace ebi {

void main_() {
    int n;
    std::cin >> n;
    std::vector<std::pair<int,int>> rc(n);
    std::cin >> rc;
    std::vector<int> p(n, -1), q(n, -1);
    for(auto [r, c]: rc) {
        r--; c--;
        if(p[r] != -1) {
            std::cout << "-1\n";
            return;
        }
        p[r] = c;
        if(q[c] != -1) {
            std::cout << "-1\n";
            return;
        }
        q[c] = r;
    }
    int ans = 0;
    rep(i,0,n) {
        if(p[i] == i) {
            assert(q[i] == i);
            continue;
        }
        ans++;
        int a = i, b = q[i];
        std::swap(p[a], p[b]);
        q[p[i]] = i;
        q[p[b]] = b;
    }
    std::cout << ans << '\n';
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4688
final_rank: 5

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <numeric>
#include <algorithm>
#include <functional>
#include <fstream>
#include <array>
#include <map>
#include <queue>
#include <time.h>

#include <limits.h>
#include <set>
#include <stack>
#include <random>
#include <complex>
#include <unordered_map>
#include <assert.h>
#include <bitset>
#include <unordered_set>
#define rep(i, s, n) for (int i = (s); (n) > i; i++)
#define REP(i, n) rep(i, 0, n)
#define RANGE(x, a, b) (min(a, b) <= (x) && (x) <= max(a, b)) // hei
#define DUPLE(a, b, c, d) (RANGE(a, c, d) || RANGE(b, c, d) || RANGE(c, a, b) || RANGE(d, a, b))
#define INCLU(a, b, c, d) (RANGE(a, c, d) && (b, c, d))
#define PW(x) ((x) * (x))
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define MODU 998244353LL
#define bitcheck(a, b) ((a >> b) & 1)
#define bitset(a, b) (a |= (1 << b))
#define bitunset(a, b) (a &= ~(1 << b))
#define MP(a, b) make_pair((a), (b))
#define Manh(a, b) (abs((a).first-(b).first) + abs((a).second - ((b).second))
#define pritnf printf
#define scnaf scanf
#define itn int
#define PI 3.141592653589

#define izryt bool
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val)
{
    std::fill((T *)array, (T *)(array + N), val);
}

//[a, b)
#define Getsum(ar, a, b) (ar[b] - ar[a])
#define INF 10000000000000000LL

struct Edge
{
    int from, to;
    ll w;
    bool operator<(const Edge &rhs) const
    {
        return MP(w, MP(from, to)) < MP(rhs.w, MP(rhs.from, rhs.to));
    }
};
typedef vector<vector<Edge>> Graph;
typedef unsigned long long ull;

#define isValid(y, x) (y >= 0 && y < n && x >= 0 && x < m)

ll mod_pow(ll x, ll n, ll mod)
{
    ll res = 1;
    while (n > 0)
    {
        if (n & 1)
            res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

int main ()  {
    int n;
    cin >> n;

    vector<set<int>> stonesV(n), stonesH(n);
    vector<int> as(n);
    REP(i,n) {
        int r,c;
        cin >> r >> c;
        r--;c--;
        stonesH[r].insert(c);
        stonesV[c].insert(r);

        as[r] = c;
    }
    
    REP(i,n) {
        if(stonesH[i].size() != 1 || stonesV[i].size() != 1) {
            cout << "-1" << endl;
            return 0;
        }
    }


    vector<int> al(n);
    int count = 0;
    REP(start, n) {
        if(al[start] == 0) {
            count++;
            int cur = start;
            do{
                al[cur] = 1;
                cur = as[cur];
            } while(cur != start);
        }
    }

    cout << n - count<< endl;

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 22768
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1000000007;
using P=pair<ll,ll>;
const ll inf = 1ll<<60;
int main() {
    ll n;
    cin >> n;
    vector<P>mp(n+1);
    vector<ll>py(n+1);
    for(ll i=0;i<n;i++){
        cin >> mp[i].first >> mp[i].second;
        py[mp[i].second]=mp[i].first;
    }
    sort(mp.begin(),mp.end());
    vector<ll>x(n+1,0),y(n+1,0);
    bool judge=false;
    for(ll i=0;i<n;i++){
        if(x[mp[i].first]>0||y[mp[i].second]>0) {
            judge=true;
            break;
        }
        x[mp[i].first]++;
        y[mp[i].second]++;
    }
    if(judge){
        cout << -1 << endl;
    }else{
        ll ans=0;
        for(ll i=0;i<n;i++){
            if(mp[i].first!=mp[i].second){
                ans++;
                ll posy=py[mp[i].second];
                swap(py[mp[i].second],py[posy]);
                swap(mp[i].second,mp[posy].second);
            }
        }
        cout << ans << endl;
    }
}
accuracy: 0.7407407407407407
time_ms: 30
memory_kb: 7032
final_rank: 20

code_snippet: #include<bits/stdc++.h>
//#include<atcoder/all>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
//using namespace atcoder;
typedef long long ll;
const ll INF = 1e18;
//typedef modint998244353 mint;
//cout << fixed << setprecision(12);

int main(){
	int n;
	cin >> n;
	vector<int> rl(n);
	vector<int> cl(n);
	vector<int> p(n);
	int r,c;
	for (int i=0; i<n; i++){
		cin >> r >> c;
		rl[r-1]++;
		cl[c-1]++;
		p[r-1]=c-1;
	}
	
	bool mode = false;
	for (int i=0; i<n; i++){
		if (rl[i] != 1) mode = true;
		if (cl[i] != 1) mode = true;
	}
	
	if (mode){
		cout << -1 << endl;
		return 0;
	}

	vector<int> pinv(n);
	for (int i=0; i<n; i++){
		pinv[p[i]] = i;
	}
	
	int ans = 0;
	for (int i=0; i<n; i++){
		// (i,i)
		if (p[i] != i){
			ans++;
			int j = pinv[i];
			pinv[p[j]] = i;
			pinv[p[i]] = j;
			swap(p[i], p[j]);
		}
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 4412
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=998244353;
#define rep(i,a) for (ll i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}


void solve();
// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t=1;
	//cin>>t;
	rep(i,t) solve();
}

void solve(){
	int N;
	cin>>N;
	vector<pair<int,int>> p(N);
	rep(i,N) cin>>p[i].first>>p[i].second;
	So(p);
	set<int> s;
	rep(i,N){
		p[i].first--;
		p[i].second--;
		s.insert(p[i].first);
		s.insert(p[i].second+N);
	}
	if((int)s.size()!=N*2){
		cout<<"-1\n";
		return ;
	}
	vector<int> seen(N);
	int ans=N;
	rep(i,N){
		if(seen[i]) continue;
		ans--;
		int ind=i;
		while(seen[ind]==0){
			seen[ind]=1;
			ind=p[ind].second;
		}
	}
	cout<<ans<<"\n";
}
accuracy: 1
time_ms: 60
memory_kb: 13640
final_rank: 12

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define all(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
using pqr = priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>;

bool chmax(ll& p, ll q) {
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

bool chmin(ll& p, ll q) {
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

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

    ll N;
    cin >> N;
    vector<pair<ll, ll>> P(N);
    rep(i, N) {
        ll U, V;
        cin >> U >> V;
        U--; V--;
        P[i] = { U,V };
    }
    sort(all(P));
    set<ll> Q;
    vll A(N);
    set<ll> D;
    rep(i, N) {
        A[i] = P[i].second;
        Q.insert(A[i]);
        D.insert(P[i].first);
    }
    if (Q.size() != N || D.size() != N) {
        cout << -1 << endl;
        return 0;
    }
    ll an = 0;
    rep(i, N) {
        while (A[i] != i) {
            ll x = i;
            ll z = A[x];
            swap(A[x], A[z]);
            an++;
        }
    }
    cout << an << endl;

}
accuracy: 1
time_ms: 50
memory_kb: 14928
final_rank: 14