// Slower C++ solution:
#include <bits/stdc++.h>

#define INF 1000000000;

#define debug(x) cerr << #x << ": " << x << '\n';

using namespace std;

using ll = long long;

using P = pair<int, int>;

const int MAX_N = (int)1e5;



template <size_t N>

class unionFindTree{

	private:

		int par[N];

		int rank[N];

		int united[N];

	public:

		unionFindTree(){

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

				par[i] = i; rank[i] = 0; united[i] = 1;

			}

		}

		void init(){

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

				par[i] = i; rank[i] = 0; united[i] = 1;

			}

		}

		int find(int x){

			if(par[x] == 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;



			if(rank[x] < rank[y]){

				par[x] = y;

				united[y] += united[x];

			}else{

				par[y] = x;

				united[x] += united[y];

				if(rank[x] == rank[y]) rank[x]++;

			}

		}

		bool same(int x, int y){

			return find(x) == find(y);

		}

		int count(int x){

			return united[find(x)];

		}

};





int main(void){

	int N, M; cin >> N >> M;

	int p[MAX_N];

	unionFindTree<MAX_N> uf;

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

		cin >> p[i];

		p[i]--;

	}

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

		int x, y; cin >> x >> y;

		uf.unite(--x, --y);

	}



	int res = 0;

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

		if(uf.same(i, p[i])) res++;

		// debug(i);

		// debug(p[i]);

		// debug(uf.same(i, p[i]));

	}



	cout << res << '\n';



	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 2.2044933647097795x):
#include <bits/stdc++.h>

#define debug(x) cerr << #x << ": " << x << '\n';

using namespace std;

using ll = long long;

using P = pair<int, int>;

const int INF = (int)1e9;



#ifndef UNION_FIND_TREE

#define UNION_FIND_TREE

class UnionFindTree{

	private:

		int N;

		unique_ptr<int[]> parent;

		unique_ptr<int[]> rank;

		unique_ptr<int[]> size;

	public:

		UnionFindTree(int N){

			this -> N = N;

			this -> parent = make_unique<int[]>(N);

			this -> rank = make_unique<int[]>(N);

			this -> size = make_unique<int[]>(N);

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

				parent[i] = i; rank[i] = 0; size[i] = 1;

			}

		}

		void init(){

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

				parent[i] = i; rank[i] = 0; size[i] = 1;

			}

		}

		int find(int x){

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

			else return parent[x] = find(parent[x]);

		}

		void unite(int x, int y){

			x = find(x); y = find(y);

			if(x == y) return;



			if(rank[x] < rank[y]){

				parent[x] = y;

				size[y] += size[x];

			}else{

				parent[y] = x;

				size[x] += size[y];

				if(rank[x] == rank[y]) rank[x]++;

			}

		}

		bool same(int x, int y){

			return find(x) == find(y);

		}

		int count(int x){

			return size[find(x)];

		}

};

#endif



int N, M;

int p[100000]; 



int main(void){

    cin >> N >> M;

    UnionFindTree ut(N);

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

        cin >> p[i];

        p[i]--;

    }

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

        int x, y; cin >> x >> y;

        ut.unite(--x, --y);

    }



    int res = 0;

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

        if(ut.same(p[i], i)) res++;

    }



    cout << res << '\n';



    return 0;

}