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: Time Limit Exceeded)

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

template <class CapType = int>
struct Dinic {
    struct Edge {
        int to, rev;
        CapType cap;
        Edge(int a, CapType b, int c) : to(a), cap(b), rev(c) {}
    };
    vector<vector<Edge>> g;
    vector<int> lev;
    size_t n;

    Dinic() = default;
    Dinic(size_t n) : n(n) {
        g.assign(n, vector<Edge>());
        lev.resize(n);
    }

    void AddEdge(int u, int v, CapType cap) {
        g[u].emplace_back(v, cap, g[v].size() - 0);
        g[v].emplace_back(u, 0, g[u].size() - 1);
    }

    bool Bfs(int s, int t) {
        fill(lev.begin(), lev.end(), -1);
        lev[s] = 0;
        vector<int> que(1, s);
        for (size_t it = 0; it < que.size(); ++it) {
            int x = que[it];
            for (const Edge &e : g[x]) {
                if (e.cap == 0) continue;
                if (lev[e.to] == -1) {
                    lev[e.to] = lev[x] + 1;
                    que.push_back(e.to);
                }
            }
        }
        return lev[t] != -1;
    }

    CapType Flow(int x, int t, CapType flow) {
        if (x == t) return flow;
        CapType res = 0;
        for (Edge &e : g[x]) {
            if (e.cap == 0) continue;
            if (lev[e.to] != lev[x] + 1) continue;
            CapType f = Flow(e.to, t, min(e.cap, flow - res));
            res += f;
            e.cap -= f;
            g[e.to][e.rev].cap += f;
        }
        if (!res) lev[x] = -1;
        return res;
    }

    CapType operator()(int s, int t) {
        CapType res = 0;
        for (; Bfs(s, t); res += Flow(s, t, numeric_limits<CapType>::max()));
        return res;
    }
};

int main() {
    int n;
    scanf("%d", &n);
    vector<int> p(n), q(n);
    for (int i = 0; i < n; ++i) scanf("%d", &p[i]);
    for (int i = 0; i < n; ++i) scanf("%d", &q[i]);
    vector<bool> used(n);
    vector<int> x(n), y(n);
    int m = 0, k = 0;
    for (int i = 0; i < n; ++i) {
        if (used[i]) continue;
        int u = i;
        while (!used[u]) {
            used[u] = true;
            x[u] = m;
            u = p[u];
        }
        m++;
    }
    fill(used.begin(), used.end(), false);
    for (int i = 0; i < n; ++i) {
        if (used[i]) continue;
        int u = i;
        while (!used[u]) {
            used[u] = true;
            y[u] = k;
            u = q[u];
        }
        k++;
    }
    Dinic<int> flow(m + k + 2);
    const int src = m + k, snk = m + k + 1;
    int ans = 0;
    for (int i = 0; i < n; ++i) {
        if (p[i] == i && q[i] == i) {
            ans++;
            continue;
        }
        if (p[i] == i) flow.AddEdge(y[i] + m, snk, 1);
        else if (q[i] == i) flow.AddEdge(src, x[i], 1);
        else if (p[i] != q[i]) flow.AddEdge(y[i] + m, x[i], 1);
        else flow.AddEdge(x[i], y[i] + m, 1), flow.AddEdge(y[i] + m, x[i], 1);
    }
    ans += flow(src, snk);
    printf("%d\n", n - ans); 
    return 0;
}