// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx,avx2,fma")

#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <cstring>
#include <chrono>
#include <vector>
#include <map>
#include <random>
#include <set>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <stdio.h>
#include <queue>
#include <bitset>
#include <cstdlib>
#include <deque>
#include <cassert>
#include <stack>
using namespace std;
 
#define mp make_pair
#define f first
#define se second
#define pb push_back
#define ppb pop_back
#define ll long long
#define ull unsigned long long
#define cntbit(x) __builtin_popcount(x)
#define endl '\n'
#define uset unordered_set
#define umap unordered_map
#define all(x) x.begin(), x.end()
#define pii pair<int, int>
#define ld long double
#define pll pair<long long, long long>

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
 
template <typename T> inline T range(T l, T r) {
	return uniform_int_distribution <T>(l, r)(rng);
}
 
template <typename T> void Min(T &a, T b) {
    a = min(a, b);
}
 
template <typename T> void Max(T &a, T b) {
    a = max(a, b);
}

template <typename T> ostream &operator << (ostream &cout, vector <T> x) {
	for(auto it = x.begin(); it != x.end(); ++it) {
		if(it == x.begin())
			cout << "{" << *it;
		else
			cout << ", " << *it;
	}
	cout << "}";
	return cout;
}

template <typename T> ostream &operator << (ostream &cout, set <T> x) {
	for(auto it = x.begin(); it != x.end(); ++it) {
		if(it == x.begin())
			cout << "{" << *it;
		else
			cout << ", " << *it;
	}
	cout << "}";
	return cout;
}

const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const int N = 2e5 + 15;
const int S = 0, T = N - 1;
int n, m, k, a[N], b[N];


struct flow {
	struct edge {
		int v, c;
	};

	int q[N], ql, qr;
	int d[N], ptr[N];

	vector <int> g[N];
	vector <edge> e;

	inline void add_edge(int u, int v, int c) {
		g[u].pb(e.size());
		e.pb({v, c});

		g[v].pb(e.size());
		e.pb({u, 0});
	}
	inline bool bfs() {
		memset(d, 0x3f, sizeof(d));
		q[ql = qr = 0] = S;
		d[S] = 0;
		while(ql <= qr) {
			int v = q[ql++];
			for(int ind : g[v]) {
				int to = e[ind].v, cap = e[ind].c;
				if(d[to] == inf && cap > 0) {
					d[to] = d[v] + 1;
					q[++qr] = to;
				}
			}
		}
		return d[T] != inf;
	}
	int dfs(int v, int cmin = inf) {
		if(v == T)
			return cmin;
		for(; ptr[v] < g[v].size(); ++ptr[v]) {
			int to = e[g[v][ptr[v]]].v, cap = e[g[v][ptr[v]]].c;
			if(d[to] == d[v] + 1 && cap > 0) {
				int flow_change = dfs(to, min(cmin, cap));
				if(flow_change > 0) {
					e[g[v][ptr[v]]].c -= flow_change;
					e[g[v][ptr[v]] ^ 1].c += flow_change;
					return flow_change;
				}
			}
		}
		return 0;
	}
	inline int calc() {
		int res = 0;
		while(bfs()) {
			memset(ptr, 0, sizeof(ptr));
			while(int flow = dfs(S))
				res += flow;
		}
		return res;
	}
} F;

int cycle[N];

int cnt_cycle;

void dfs(int v) {
	if(!cycle[a[v]]) {
		cycle[a[v]] = cycle[v];
		dfs(a[v]);
	}
}

main() {
	scanf("%d", &n);
	for(int i = 1; i <= n + n; ++i) {
		scanf("%d", &a[i]);
		++a[i];
		if(i > n)
			a[i] += n;
	}
	for(int i = 1; i <= n + n; ++i) {
		if(!cycle[i]) {
			cycle[i] = ++cnt_cycle;
			dfs(i);
		}
	}
	int ans = n;
	for(int i = 1; i <= n; ++i) {
		if(a[i] == i && a[i + n] == i + n) {
			--ans;
		}
		else if(a[i] == i)
			F.add_edge(cycle[i + n], T, 1);
		else if(a[i + n] == i + n)
			F.add_edge(S, cycle[i], 1);
		else {
			F.add_edge(cycle[i + n], cycle[i], 1);
			if(a[i] == a[i + n] - n)
				F.add_edge(cycle[i], cycle[i + n], 1);
		}
	}
	printf("%d\n", ans - F.calc());
	return 0;
}

Measured memory_bytes: 16112