#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 998244353
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())

int n,p[100005],q[100005],base;
struct uf{
	int par[100005];
	void init(){rep(i,100005)par[i]=i;}
	int find(int x){ if(x==par[x]) return x;else return par[x]=find(par[x]);}
	void unite(int x,int y){
		x = find(x); y = find(y); if(x == y) return;
		par[x] = y;
	}
	bool same(int x,int y){ return find(x) == find(y); }
}a,b;
int gain[200005];
vector<P1>edgee;

template<int SZ> struct Dinic{
	struct edgeE
	{
		int to,cap,rev;
	};
	vector<edgeE>G[SZ];
	bool used[SZ];
	int ind[SZ],level[SZ];
	void add_edge(int from,int to,int cap)
	{
		G[from].push_back((edgeE){to,cap,G[to].size()});
		G[to].push_back((edgeE){from,0,G[from].size()-1});
	}
	void bfs(int s){
		memset(level,-1,sizeof(level));
		memset(ind,0,sizeof(ind));
		queue<int>q;
		level[s] = 0; q.push(s);
		while(!q.empty()){
			int v = q.front(); q.pop();
			for(int i=0;i<G[v].size();i++){
				edgeE &e = G[v][i];
				if(e.cap>0 && level[e.to]<0){
					level[e.to] = level[v]+1;
					q.push(e.to);
				}
			}
		}
	}
	int dfs(int v,int t,int f)
	{ 
		if(v==t) return f;
		//for(int i=itr[v];i<G[v].size();i++)
		for(;ind[v]<G[v].size();ind[v]++)
		{
			edgeE &e=G[v][ind[v]];
			if(level[e.to] != level[v]+1 || e.cap == 0) continue;
		//	if(e.cap>0 && level[v] < level[e.to])
			{ 
				int d=dfs(e.to,t,min(f,e.cap));
				if(d>0) 
				{ 
					e.cap-=d;
					G[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	int max_flow(int s,int t)
	{ 
		int flow=0,f;
		while(bfs(s),level[t]>=0)
		{
			memset(ind,0,sizeof(ind));
			while( (f=dfs(s,t,INF)) > 0){
				flow += f;
			}
		}
		return flow;
	}
	bool U[SZ];
    void DFS(int v){
        if(U[v]) return ; U[v] = 1;
        for(int i=0;i<G[v].size();i++){
            if(G[v][i].cap == 0) continue;
            DFS(G[v][i].to);
        }
    }
};
Dinic<200005>kaede;

int main(){
	scanf("%d",&n);
	a.init(); b.init();
	//0...p[i] 1...i
	rep(i,n){
		scanf("%d",&p[i]);
		a.unite(i,p[i]);
	}
	//0...i 1...q[i]
	rep(i,n){
		scanf("%d",&q[i]);
		if(q[i] != i) base++;
		b.unite(i,q[i]);
	}
	rep(i,n){
		if(p[i] == q[i] && p[i] == i) continue;
		else if(p[i] == i){
			gain[b.find(i)+n] += -1;
		}else if(q[i] == i){
			gain[a.find(i)] += 1;
		}
		else if(p[i] == q[i]){
			edgee.pb(mp(1,mp(b.find(i)+n,a.find(i))));
			edgee.pb(mp(1,mp(a.find(i),b.find(i)+n)));
		}
		else{
			edgee.pb(mp(1,mp(b.find(i)+n,a.find(i))));
		}
	}
	rep(i,2*n){
		if(gain[i] > 0){
			base += gain[i];
			kaede.add_edge(200001,i,gain[i]);
		}
		else if(gain[i] < 0){
			kaede.add_edge(i,200002,-gain[i]);
		}
	}
	rep(i,edgee.size()) kaede.add_edge(edgee[i].sc.fi,edgee[i].sc.sc,edgee[i].fi);
	cout << base - kaede.max_flow(200001,200002) << endl;
}

Measured memory_bytes: 18800