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)

#include<cstdio>
#include<algorithm>
#include<vector>
#define N_ 201000
using namespace std;
int A[N_], B[N_], DegA[N_], DegB[N_], Q[N_], head, tail, vis[N_], CA, CB;
int n, Num[N_][2];
vector<int>GA[N_], GB[N_];

#define N_ 300100
#define M_ 2001000
struct MaxFlow {
	vector<int>G[N_];
	struct Edge {
		int b, e, f;
	}E[M_];
	int EC, flow, PV[N_], Q[N_], Level[N_], n, source, sink, INF = 1e9;
	void init(int N, int S, int T) {
		source = S, sink = T, flow = EC = 0;
		n = N;
		for (int i = 0; i <= n; i++)G[i].clear();
	}
	void Add_Edge(int a, int b, int f) {
		G[a].push_back(EC);
		G[b].push_back(EC + 1);
		E[EC++] = { a,b,f };
		E[EC++] = { b,a,0 };
	}
	int BlockFlow(int a, int f) {
		if (a == sink)return f;
		for (int &i = PV[a]; i >= 0; i--) {
			int t = G[a][i];
			if (E[t].f && Level[E[t].e] == Level[a] + 1) {
				int ff = BlockFlow(E[t].e, min(E[t].f, f));
				if (ff) {
					E[t].f -= ff;
					E[t ^ 1].f += ff;
					return ff;
				}
			}
		}
		return 0;
	}
	bool GetLevel() {
		int head = 0, tail = 0, i;
		for (i = 1; i <= n; i++)Level[i] = -1;
		Q[++tail] = source; Level[source] = 0;
		while (head < tail) {
			int x = Q[++head];
			for (auto &t : G[x]) {
				if (E[t].f && Level[E[t].e] == -1) {
					Level[E[t].e] = Level[x] + 1;
					Q[++tail] = E[t].e;
				}
			}
		}
		return Level[sink] != -1;
	}
	void Dinic() {
		int i, t;
		flow = 0;
		while (GetLevel()) {
			for (i = 1; i <= n; i++)PV[i] = G[i].size() - 1;
			while (t = BlockFlow(source, INF)) {
				flow += t;
			}
		}
	}
}G1;

int main() {
	int i;
	scanf("%d", &n);
	for (i = 0; i < n; i++) {
		scanf("%d", &A[i]);
		DegA[A[i]]++;
	}
	for (i = 0; i < n; i++) {
		scanf("%d", &B[i]);
		DegB[B[i]]++;
	}

	for (i = 0; i < n; i++) {
		if (!DegA[i])Q[++tail] = i;
	}
	while (head < tail) {
		int x = Q[++head];
		DegA[A[x]]--;
		if (!DegA[A[x]])Q[++tail] = A[x];
	}
	for (i = 0; i < n; i++) {
		if (DegA[i] && !vis[i]) {
			int x = i;
			vector<int>T;
			while (!vis[x]) {
				vis[x] = 1;
				T.push_back(x);
				x = A[x];
			}
			if (T.size() == 1)continue;
			GA[++CA] = T;
			for (auto &t : T)Num[t][0] = CA;
		}
	}
	for (i = 0; i < n; i++)vis[i] = 0;

	head = tail = 0;

	for (i = 0; i < n; i++) {
		if (!DegB[i])Q[++tail] = i;
	}
	while (head < tail) {
		int x = Q[++head];
		DegB[B[x]]--;
		if (!DegB[B[x]])Q[++tail] = B[x];
	}
	for (i = 0; i < n; i++) {
		if (DegB[i] && !vis[i]) {
			int x = i;
			vector<int>T;
			while (!vis[x]) {
				vis[x] = 1;
				T.push_back(x);
				x = B[x];
			}
			if (T.size() == 1)continue;
			GB[++CB] = T;
			for (auto &t : T)Num[t][1] = CB;
		}
	}

	long long res = 0;
	G1.init(CA + CB + 2, CA + CB + 1, CA + CB + 2);
	for(i=1;i<=CA;i++){
		G1.Add_Edge(G1.source, i, (int)GA[i].size());
		res += GA[i].size();
	}
	for (i = 1; i <= CB; i++) {
		G1.Add_Edge(CA + i, G1.sink, (int)GB[i].size());
		res += GB[i].size();
	}
	for (i = 0; i < n; i++) {
		if (Num[i][0] && Num[i][1]) {
			G1.Add_Edge(Num[i][0], CA + Num[i][1], 1);
			if (A[i] == B[i]) {
				G1.Add_Edge(Num[i][0], CA + Num[i][1], 1);
			}
		}
	}
	G1.Dinic();
	printf("%lld\n", res - G1.flow);
}