//インクルード(アルファベット順)
#include<algorithm>//sort,二分探索,など
#include<bitset>//固定長bit集合
#include<chrono>//実行時間計測
#include<cmath>//pow,logなど
#include<complex>//複素数
#include<deque>//両端アクセスのキュー
#include<functional>//sortのgreater
#include<iomanip>//setprecision(浮動小数点の出力の誤差)
#include<iostream>//入出力
#include<iterator>//集合演算(積集合,和集合,差集合など)
#include<map>//map(辞書)
#include<numeric>//iota(整数列の生成),gcdとlcm,accumulate
#include<queue>//キュー
#include<set>//集合
#include<stack>//スタック
#include<string>//文字列
#include<unordered_map>//順序保持しないmap
#include<unordered_set>//順序保持しないset
#include<utility>//pair
#include<vector>//可変長配列
#include<stdio.h>

using namespace std;
typedef long long ll;
//マクロ
//forループ
//引数は、(ループ内変数,動く範囲)か(ループ内変数,始めの数,終わりの数)、のどちらか
//Dがついてないものはループ変数は1ずつインクリメントされ、Dがついてるものはループ変数は1ずつデクリメントされる
#define REP(i,n) for(ll i=0;i<ll(n);i++)
#define REPD(i,n) for(ll i=n-1;i>=0;i--)
#define FOR(i,a,b) for(ll i=a;i<=ll(b);i++)
#define FORD(i,a,b) for(ll i=a;i>=ll(b);i--)
//xにはvectorなどのコンテナ
#define ALL(x) x.begin(),x.end()
#define SIZE(x) ll(x.size())
//定数
#define INF 1000000000000 //10^12:∞
#define MOD 1000000007 //10^9+7:合同式の法
#define MAXR 100000 //10^5:配列の最大のrange
//略記
#define PB push_ABck //挿入
#define MP make_pair //pairのコンストラクタ
#define F first //pairの一つ目の要素
#define S second //pairの二つ目の要素
#define PI 3.14159265358979323846264338327950L


#define YESNO(T) if(T){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}
#define yesno(T) if(T){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}
#define YesNo(T) if(T){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}

#define int long long
#define Graph vector<vector<int> >
#define PII pair<int,int>
#define VI vector<int>
#define VVI vector<vector<int> >
#define VPII vector<pair<int,int> >


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ここにグローバル変数宣言




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ここに関数宣言


struct UnionFind {
	vector<int> d; //iが子ならd[i]は親のidでiが親ならd[i]は -サイズ
	UnionFind(int n): d(n, -1) {}
	int find(int x) {
		if (d[x] < 0)return x;//親なら自分自身の番号を返す
		else return d[x] = find(d[x]); //経路圧縮　メモ化
	}
	bool unite(int x, int y) { //voidでもいいが、くっつけられるか判定できた方が嬉しいときもある
		x = find(x); y = find(y); //根同士をくっつけるため
		if (x == y) return false;//統合できない(しない)
		if (-d[x] < -d[y]) swap(x, y);
		d[x] += d[y]; //親のサイズの更新 サイズが大きい方に小さい方を統合
		d[y] = x;//yは親ではなくなったのでyの親をｘに設定
		return true;//統合できた
	}
	int size(int x) {return -d[find(x)];}
	bool same(int x, int y) {return find(x) == find(y);}
};




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
signed main() {
	//入力の高速化
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

	VI p(N);

	UnionFind uf(N);

	REP(i, N) {cin >> p[i];p[i]--;}

	REP(i, M) {
		int x, y;
		cin >> x >> y;
		x--; y--;
		uf.unite(p[x], p[y]);
	}

	int ans = 0;

	REP(i, N) {
		if (uf.same(p[i], i))ans++;
		//cout << (p[i]) << " " << i << endl;;
	}

	
	cout << ans << endl;












































	return 0;
}


Measured memory_bytes: 4764