Problem:
Score : 1600 points

Problem Statement

Snuke has permutations (P_0,P_1,\cdots,P_{N-1}) and (Q_0,Q_1,\cdots,Q_{N-1}) of (0,1,\cdots,N-1).

Now, he will make new permutations A and B of (0,1,\cdots,N-1), under the following conditions:

For each i (0 \leq i \leq N-1), A_i should be i or P_i.

For each i (0 \leq i \leq N-1), B_i should be i or Q_i.

Let us define the distance of permutations A and B as the number of indices i such that A_i \neq B_i.
Find the maximum possible distance of A and B.

Constraints

1 \leq N \leq 100000

0 \leq P_i \leq N-1

P_0,P_1,\cdots,P_{N-1} are all different.

0 \leq Q_i \leq N-1

Q_0,Q_1,\cdots,Q_{N-1} are all different.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
P_0 P_1 \cdots P_{N-1}
Q_0 Q_1 \cdots Q_{N-1}

Output

Print the maximum possible distance of A and B.

Sample Input 1

4
2 1 3 0
0 2 3 1

Sample Output 1

3

For example, if we make A=(0,1,2,3) and B=(0,2,3,1), the distance will be 3, which is the maximum result possible.

Sample Input 2

10
0 4 5 3 7 8 2 1 9 6
3 8 5 6 4 0 2 1 7 9

Sample Output 2

8

Sample Input 3

32
22 31 30 29 7 17 16 3 14 9 19 11 2 5 10 1 25 18 15 24 20 0 12 21 27 4 26 28 8 6 23 13
22 3 2 7 17 9 16 4 14 8 19 26 28 5 10 1 25 18 15 13 11 0 12 23 21 20 29 24 27 6 30 31

Sample Output 3

28

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#define _USE_MATH_DEFINES
#include <array>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>
#include <random>
#include <ctime>

using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int, int> ii;
const int INF = 1 << 29;
const int MOD = 1e9 + 7;

#define SZ(x) (int)(x.size())

struct Edge {
  int v, c, f, dual;
  Edge() {}
  Edge(int v, int c, int dual) : v(v), c(c), dual(dual) { f = 0; }
};

template<size_t N>
struct maxflow {
  vector<Edge> a[N];
  vector<Edge>::iterator idx[N];
  int d[N];

  void add_edge(int u, int v, int c) {
    a[u].emplace_back(v, c, SZ(a[v]));
    a[v].emplace_back(u, 0, SZ(a[u]) - 1);
  }
  void add_bidirection_edge(int u, int v, int c) {
    a[u].emplace_back(v, c, SZ(a[v]));
    a[v].emplace_back(u, c, SZ(a[u]) - 1);
  }
  int augment(int u, int t, int bound) {
    if (u == t) return bound;
    int ret = 0;
    // current arc optimization
    for (auto it = a[u].begin(); it != a[u].end() && ret < bound; ++it) {
      if (it->c && d[it->v] == d[u] + 1) {
        int aug = augment(it->v, t, min(it->c, bound - ret));
        ret += aug;
        it->c -= aug;
        a[it->v][it->dual].c += aug;
      }
    }
    if (ret == 0) d[u] = -1;
    return ret;
  }
  int n;
  bool path(int s, int t) {
    fill(d, d + n, -1);
    d[s] = 0;
    queue<int> Q;
    Q.push(s);
    while (!Q.empty()) {
      int u = Q.front();
      Q.pop();
      for (auto& p : a[u]) {
        if (p.c && d[p.v] == -1) {
          Q.push(p.v);
          d[p.v] = d[u] + 1;
          if (p.v == t) return true;
        }
      }
    }
    return false;
  }
  void init(int n) {
    this->n = n;
    for (int i = 0; i < n; ++i) a[i].clear();
  }
  int dinic(int s, int t) {
    int ret = 0;
    while (path(s, t)) {
      // current arc optimization
      // for (int i = 0; i < n; ++i) idx[i] = a[i].begin();
      while (int aug = augment(s, t, INF)) {
        ret += aug;
      }
    }
    return ret;
  }
};

const int N = 2e5 + 10;

int main() {
  int n;
  scanf("%d", &n);
  vector<int> a(n), b(n);
  for (int i = 0; i < n; ++i) {
    scanf("%d", &a[i]);
  }
  for (int i = 0; i < n; ++i) {
    scanf("%d", &b[i]);
  }
  vector<int> ca(n, -1), cb(n, -1);
  int len = 0;
  for (int i = 0; i < n; ++i) {
    if (ca[i] >= 0) continue;
    ca[i] = len++;
    for (int j = a[i]; j != i; j = a[j]) ca[j] = ca[i];
  }
  for (int i = 0; i < n; ++i) {
    if (cb[i] >= 0) continue;
    cb[i] = len++;
    for (int j = b[i]; j != i; j = b[j]) cb[j] = cb[i];
  }
  int s = len, t = s + 1;
  maxflow<N> flow;
  flow.init(len + 2);
  int ret = 0;
  map<ii, int> cnt;
  for (int i = 0; i < n; ++i) {
    if (a[i] == i && b[i] == i) {
      ++ret;
    } else if (a[i] != i && b[i] == i) {
      cnt[{ca[i], t}]++;
      // flow.add_edge(ca[i], t, 1);
    } else if (a[i] == i && b[i] != i) {
      cnt[{s, cb[i]}]++;
      // flow.add_edge(s, cb[i], 1);
    } else {
      if (a[i] == b[i]) {
        // flow.add_bidirection_edge(ca[i], cb[i], 1);
        cnt[{ca[i], cb[i]}]++;
        cnt[{cb[i], ca[i]}]++;
      } else {
        cnt[{ca[i], cb[i]}]++;
        // flow.add_edge(ca[i], cb[i], 1);
      }
    }
  }
  for (auto& it : cnt) {
    int x = it.first.first, y = it.first.second;
    flow.add_edge(x, y, it.second);
  }
  ret += flow.dinic(s, t);
  printf("%d\n", n - ret);
  return 0;
}