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

#define int long long

#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,a,b) for(int i=(a);i<(b);i++)
#define pb push_back
#define eb emplace_back
#define all(v) (v).begin(),(v).end()
#define fi first
#define se second

using vint=vector<int>;
using pint=pair<int,int>;
using vpint=vector<pint>;

template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

template<class A,class B>
ostream& operator<<(ostream& ost,const pair<A,B>&p){
    ost<<"{"<<p.first<<","<<p.second<<"}";
    return ost;
}

template<class T>
ostream& operator<<(ostream& ost,const vector<T>&v){
    ost<<"{";
    for(int i=0;i<v.size();i++){
        if(i)ost<<",";
        ost<<v[i];
    }
    ost<<"}";
    return ost;
}

struct Dinic{
    using F=long long;
    static const F INF;

    struct Edge{
        int dst;
        F cap;
        int rev;
        Edge(int dst,F cap,int rev):dst(dst),cap(cap),rev(rev){}
    };

    int n;
    vector<vector<Edge>>G;
    vector<int>iter,level;
    Dinic(int n):n(n),G(n),iter(n),level(n){}
    inline void addEdge(int src,int dst,F cap){
        G[src].push_back(Edge(dst,cap,G[dst].size()));
        G[dst].push_back(Edge(src,0,G[src].size()-1));
    }
    inline void addUndirectedEdge(int src,int dst,F cap){
        G[src].push_back(Edge(dst,cap,G[dst].size()));
        G[dst].push_back(Edge(src,cap,G[src].size()-1));
    }

    void bfs(int s){
        level.assign(n,-1);
        queue<int>que;
        level[s]=0;
        que.push(s);
        while(que.size()){
            int u=que.front();
            que.pop();
            for(auto &e:G[u]){
                if(e.cap==0||level[e.dst]!=-1)continue;
                level[e.dst]=level[u]+1;
                que.push(e.dst);
            }
        }
    }

    F dfs(const int &s,const int &u,F cur){
        if(s==u)return cur;
        F sum=0;
        for(int &i=iter[u];i<G[u].size();i++){
            Edge &e=G[u][i],&ee=G[e.dst][e.rev];
            const int &v=e.dst;
            if(level[v]>=level[u]||ee.cap==0)continue;
            F f=dfs(s,v,min(cur-sum,ee.cap));
            if(f<=0)continue;
            ee.cap-=f;e.cap+=f;
            sum+=f;
            if(sum==cur)break;
        }
        return sum;
    }


    F maxFlow(int s,int t){
        F flow=0;
        while(true){
            bfs(s);
            if(level[t]==-1)return flow;
            iter.assign(n,0);
            flow+=dfs(s,t,INF);
        }
    }
};
const Dinic::F Dinic::INF=1ll<<50;

struct UnionFindTree{
    vector<int>par,sz;
    UnionFindTree(int n){
        par.resize(n);
        sz.resize(n);
        for(int i=0;i<n;i++){
            par[i]=i;
            sz[i]=1;
        }
    }
    int find(int x){
        return x==par[x]?x:par[x]=find(par[x]);
    }
    void unite(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        if(sz[x]<sz[y])swap(x,y);
        sz[x]+=sz[y];
        par[y]=x;
    }
    bool areSame(int x,int y){
        return find(x)==find(y);
    }
    int size(int x){
        return sz[find(x)];
    }
};

signed main(){
    int N;scanf("%lld",&N);

    vector<int>P(N),Q(N);
    rep(i,N)scanf("%lld",&P[i]);
    rep(i,N)scanf("%lld",&Q[i]);


    int base=0;
    UnionFindTree uf(2*N);
    vint uku(N);
    rep(i,N){
        if(i==P[i]&&i==Q[i]){
            base++;
            uku[i]=1;
            continue;
        }
        uf.unite(i,P[i]);
        uf.unite(i+N,Q[i]+N);
    }

    vint rs;
    rep(i,N){
        if(uku[i])continue;
        if(uf.find(i)==i)rs.pb(i);
        if(uf.find(i+N)==i+N)rs.pb(i+N);
    }
    sort(all(rs));

    int src=rs.size();
    int snk=src+1;
    Dinic d(rs.size()+2);

    auto id=[&](int v){
        return lower_bound(all(rs),uf.find(v))-rs.begin();
    };

    rep(i,N){
        if(uku[i])continue;
        if(i==P[i]){
            d.addEdge(id(i+N),snk,1);
        }
        else{
            d.addEdge(id(i+N),id(i),1);
            if(P[i]==Q[i])d.addEdge(id(i),id(i+N),1);
        }

        if(i==Q[i]){
            d.addEdge(src,id(i),1);
        }
    }

    int ans=N-base-d.maxFlow(src,snk);
    printf("%lld\n",ans);
    return 0;
}

Measured memory_bytes: 22884