// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cstring>

#include <functional>

#include <algorithm>

#include <vector>

#include <string>

#include <queue>

#include <stack>

#include <map>

#include <set>

using namespace std;



template<class T, class Compare = greater<T> >

using MinHeap = priority_queue<T, vector<T>, Compare>;

template<class T, class Compare = less<T> >

using MaxHeap = priority_queue<T, vector<T>, Compare>;

using llong = long long;



//===

struct UnionFind {

    int n;

    vector<int> parent;



    UnionFind() {}

    UnionFind(int nmemb) { init(nmemb); }



    void init(int nmemb) {

        parent.clear();

        parent.assign(nmemb, -1);

    }



    int root(int x) {

        if (parent[x] < 0) {

            return x;

        }

        return parent[x] = root(parent[x]);

    }



    bool same(int x, int y) { return root(x) == root(y); }

    int size(int x) { return -(parent[root(x)]); }



    void unite(int x, int y) {

        x = root(x);

        y = root(y);



        if (x == y) return;



        parent[x] += parent[y];

        parent[y] = x;

        

        return;

    }

};

//===



llong n, m;

llong p[100005];

llong x, y;



int main() {

    UnionFind s(100005);

    

    cin >> n >> m;

    for (int i = 1; i <= n; i++) {

        cin >> p[i];

    }



    for (int i = 0; i < m; i++) {

        cin >> x >> y;

        s.unite(p[x], p[y]);

    }



    llong ans = 0;

    for (int i = 1; i <= n; i++) {

        if (s.same(p[i], i)) ans++;

    }



    cout << ans << endl;



    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.3991047657440872x):
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cassert>

#include <functional>

#include <algorithm>

#include <string>

#include <vector>

#include <set>

#include <map>

#include <queue>

#include <stack>

using namespace std;

using llong = long long;



//===

struct UnionFind {

    int n;

    vector<int> parent;



    UnionFind() {}

    UnionFind(int nmemb) {

        init(nmemb);

    };



    void init(int nmemb) {

        parent.clear();

        parent.assign(nmemb, -1);

    };



    int root(int x) {

        if (parent[x] < 0) {

            return x;

        }

        return parent[x] = root(parent[x]);

    };



    void unite(int x, int y) {

        x = root(x);

        y = root(y);



        if (x == y) return;



        if (parent[y] < parent[x]) swap(x, y);



        parent[x] += parent[y];

        parent[y] = x;

        

        return;

    };

    

    bool same(int x, int y) {

        return root(x) == root(y);

    };

    int size(int x) {

        return -(parent[root(x)]);

    };

};

//===



llong n, m;

llong p[100005];

llong x, y;



int main() {

    cin >> n >> m;

    for (int i = 0; i < n; i++) {

        cin >> p[i];

    }



    UnionFind uf(n + 1);



    for (int i = 0; i < m; i++) {

        cin >> x >> y;

        uf.unite(p[x - 1], p[y - 1]);

    }



    llong ans = 0;

    for (int i = 1; i <= n; i++) {

        if (uf.same(i, p[i - 1])) ans++;

    }



    cout << ans << endl;



    return 0;

}