We have a permutation of the integers from 1 through N, p_1, p_2, .., p_N.
We also have M pairs of two integers between 1 and N (inclusive), represented as (x_1,y_1), (x_2,y_2), .., (x_M,y_M).
AtCoDeer the deer is going to perform the following operation on p as many times as desired so that the number of i (1 ≤ i ≤ N) such that p_i = i is maximized:
 - Choose j such that 1 ≤ j ≤ M, and swap p_{x_j} and p_{y_j}.
Find the maximum possible number of i such that p_i = i after operations.

-----Constraints-----
 - 2 ≤ N ≤ 10^5
 - 1 ≤ M ≤ 10^5
 - p is a permutation of integers from 1 through N.
 - 1 ≤ x_j,y_j ≤ N
 - x_j ≠ y_j
 - If i ≠ j, \{x_i,y_i\} ≠ \{x_j,y_j\}.
 - All values in input are integers.

-----Input-----
Input is given from Standard Input in the following format:
N M
p_1 p_2 .. p_N
x_1 y_1
x_2 y_2
:
x_M y_M

-----Output-----
Print the maximum possible number of i such that p_i = i after operations.

-----Sample Input-----
5 2
5 3 1 4 2
1 3
5 4

-----Sample Output-----
2

If we perform the operation by choosing j=1, p becomes 1 3 5 4 2, which is optimal, so the answer is 2.

Difficulty: HARD

Solutions:
import sys
readline = sys.stdin.readline

class UnionFind(object):

	def __init__(self, n):
		self._par = list(range(n))
		self.size = [1] * n

	def root(self, v):
		if self._par[v] == v:
			return v
		self._par[v] = self.root(self._par[v])
		return self._par[v]

	def unite(self, u, v):
		(u, v) = (self.root(u), self.root(v))
		if u == v:
			return False
		if self.size[u] > self.size[v]:
			(u, v) = (v, u)
		self.size[v] += self.size[u]
		self._par[u] = v

	def is_connected(self, u, v):
		return self.root(u) == self.root(v)
(n, m) = map(int, readline().split())
P = list(map(lambda x: int(x) - 1, readline().split()))
uf = UnionFind(n)
for _ in range(m):
	(x, y) = map(lambda x: int(x) - 1, readline().split())
	uf.unite(x, y)
ans = 0
for i in range(n):
	if uf.is_connected(i, P[i]):
		ans += 1
print(ans)


def f(x):
	while q[x] >= 0:
		x = q[x]
	return x
(N, M) = map(int, input().split())
p = list(map(int, input().split()))
q = [-1] * N
for _ in range(M):
	(x, y) = map(lambda x: f(int(x) - 1), input().split())
	if x == y:
		continue
	elif x < y:
		(x, y) = (y, x)
	q[x] += q[y]
	q[y] = x
tree = [[] for n in range(N)]
for n in range(N):
	tree[f(n)].append(n)
ans = 0
for n in range(N):
	ans += len(set(tree[n]) & {p[i] - 1 for i in tree[n]})
print(ans)


class UnionFind:

	def __init__(self, n):
		self.tree = [-1 for i in range(n)]
		return

	def union(self, x, y):
		xroot = self.root(x)
		yroot = self.root(y)
		if xroot == yroot:
			return
		if self.tree[xroot] > self.tree[yroot]:
			(xroot, yroot) = (yroot, xroot)
		self.tree[xroot] += self.tree[yroot]
		self.tree[yroot] = xroot
		return

	def root(self, x):
		qu = []
		while self.tree[x] >= 0:
			qu.append(x)
			x = self.tree[x]
		for i in qu:
			self.tree[i] = x
		return x

	def same(self, x, y):
		return self.root(x) == self.root(y)

	def size(self):
		arr = [0 for i in range(len(self.tree))]
		for i in range(len(self.tree)):
			arr[self.root(i)] += 1
		for i in range(len(self.tree)):
			if self.root(i) != i:
				arr[i] += arr[self.root(i)]
		return arr

	def getnumroots(self):
		ans = 0
		for i in self.tree:
			if i < 0:
				ans += 1
		return ans

	def getelements(self):
		arr = [-1 for i in range(len(self.tree))]
		ans = []
		c = 0
		for i in range(len(self.tree)):
			if arr[self.root(i)] == -1:
				arr[self.root(i)] = c
				ans.append([i])
				c += 1
			else:
				ans[arr[self.root(i)]].append(i)
		return ans
from sys import stdin

def input():
	return stdin.readline()

def main():
	(n, m) = map(int, input().split())
	p = list(map(int, input().split()))
	uf = UnionFind(n)
	ans = 0
	for i in range(m):
		(x, y) = map(int, input().split())
		uf.union(x - 1, y - 1)
	arr = uf.getelements()
	for i in range(len(arr)):
		temp = []
		for j in arr[i]:
			temp.append(p[j] - 1)
		ans += len(set(temp).intersection(arr[i]))
	print(ans)

def __starting_point():
	main()
__starting_point()


import sys
from collections import deque
readline = sys.stdin.readline
(n, m) = map(int, readline().split())
P = list(map(lambda x: int(x) - 1, readline().split()))
G = [set() for _ in range(n)]
for i in range(m):
	(x, y) = map(lambda x: int(x) - 1, readline().split())
	G[x].add(y)
	G[y].add(x)
D = {}
cnt = 0
V = [-1] * n
for i in range(n):
	if V[i] != -1:
		continue
	V[i] = cnt
	que = deque([i])
	D[cnt] = set([P[i]])
	while que:
		nw = que.popleft()
		for nx in G[nw]:
			if V[nx] != -1:
				continue
			D[cnt].add(P[nx])
			V[nx] = cnt
			que.append(nx)
	cnt += 1
print(sum([int(i in D[V[i]]) for i in range(n)]))


(N, M) = map(int, input().split())
p = list(map(int, input().split()))
p = [0] + p
par = list(range(N + 1))

def find(x):
	if par[x] == x:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	if find(x) != find(y):
		par[find(x)] = y
for _ in range(M):
	(a, b) = map(int, input().split())
	unite(a, b)
ans = 0
for i in range(1, N + 1):
	if find(p[i]) == find(p[p[i]]):
		ans += 1
print(ans)


(N, M) = list(map(int, input().split()))
p = list(map(int, input().split()))
parent = [k for k in range(N)]

def find(x):
	if parent[x] == x:
		return x
	else:
		parent[x] = find(parent[x])
		return find(parent[x])

def unite(x, y):
	parent[find(x)] = find(y)
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	unite(x - 1, y - 1)
ans = 0
for k in range(N):
	if find(k) == find(p[k] - 1):
		ans += 1
print(ans)


from collections import deque
(N, M) = map(int, input().split())
plist = list(map(int, input().split()))
pilist = []
for (i, p) in enumerate(plist):
	pilist.append((p, i + 1))
pilist.sort(key=lambda x: x[0])
dic = {k: [] for k in range(N + 1)}
for _ in range(M):
	(x, y) = map(int, input().split())
	dic[plist[x - 1]].append(plist[y - 1])
	dic[plist[y - 1]].append(plist[x - 1])
groups = []
done = [0] * (N + 1)
for p in range(1, N + 1):
	if done[p] == 0:
		done[p] = 1
		group_p = [p]
		group_i = [pilist[p - 1][1]]
		queue = deque([p])
		while queue:
			q = queue.pop()
			for q_n in dic[q]:
				if done[q_n] == 0:
					done[q_n] = 1
					group_p.append(q_n)
					group_i.append(pilist[q_n - 1][1])
					queue.append(q_n)
		groups.append((group_p, group_i))
ans = 0
for group in groups:
	p = set(group[0])
	i = set(group[1])
	ans += len(p & i)
print(ans)


(n, m) = map(int, input().split())
pn = list(map(lambda x: int(x) - 1, input().split()))
ls = [-1] * n
for i in pn:
	ls[pn[i]] = i
par = [i for i in range(n)]

def find(x):
	if par[x] == x:
		return x
	else:
		s = find(par[x])
		par[x] = s
		return s

def unite(x, y):
	s = find(x)
	t = find(y)
	if s > t:
		par[s] = t
	else:
		par[t] = s
for _ in range(m):
	(x, y) = map(lambda x: int(x) - 1, input().split())
	unite(ls[x], ls[y])
ans2 = 0
for i in range(n):
	place1 = ls[pn[i]]
	place2 = ls[i]
	if find(place1) == find(place2):
		ans2 += 1
print(ans2)


import sys, math, collections, itertools
input = sys.stdin.readline
(N, M) = list(map(int, input().split()))
P = list(map(int, input().split()))
bridge = [[] for i in range(N + 1)]
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	bridge[x].append(y)
	bridge[y].append(x)
memo = [-1] * (N + 1)
q = collections.deque([])
novisit = set(range(1, N + 1))
tmp = 0
while novisit:
	q.append(novisit.pop())
	tmp += 1
	while q:
		now = q.pop()
		memo[now] = tmp
		for bri in bridge[now]:
			if bri in novisit:
				q.append(bri)
				novisit.discard(bri)
cnt = 0
for i in range(N):
	if i + 1 == P[i]:
		cnt += 1
	elif i + 1 != P[i] and memo[P[i]] == memo[i + 1]:
		cnt += 1
print(cnt)


(N, M) = map(int, input().split())
(*P,) = map(int, input().split())
xy = [list(map(int, input().split())) for _ in range(M)]

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x
uf = UnionFind(N)
for (x, y) in xy:
	uf.union(x - 1, y - 1)
ans = sum((uf.find(i) == uf.find(P[i] - 1) for i in range(N)))
print(ans)


def find(x):
	if par[x] < 0:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def union(x, y):
	x = find(x)
	y = find(y)
	if x == y:
		return
	if par[x] > par[y]:
		(x, y) = (y, x)
	par[x] += par[y]
	par[y] = x

def size(x):
	return -par[find(x)]

def same(x, y):
	return find(x) == find(y)
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
par = [-1] * n
pos = [-1] * n
for i in range(n):
	pos[p[i] - 1] = i
for _ in range(m):
	(x, y) = map(int, input().split())
	union(x - 1, y - 1)
res = 0
for i in range(n):
	if same(i, pos[i]):
		res += 1
print(res)


class union_find:

	def __init__(self, N):
		self.par = [-1] * N

	def find(self, x):
		if self.par[x] < 0:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return False
		else:
			if self.par[x] > self.par[y]:
				(x, y) = (y, x)
			self.par[x] += self.par[y]
			self.par[y] = x
			return True

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def size(self, x):
		return -self.par[self.find(x)]
(N, M) = map(int, input().split())
P = list(map(lambda x: int(x) - 1, input().split()))
uf = union_find(N)
for _ in range(M):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	uf.unite(x, y)
ans = 0
for i in range(N):
	if uf.same(P[i], i):
		ans += 1
print(ans)


(n, m) = map(int, input().split())
par = [-1] * n

def find(x):
	if par[x] < 0:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	(px, py) = (find(x), find(y))
	if px == py:
		return False
	else:
		if px < py:
			(px, py) = (py, px)
		par[px] += par[py]
		par[py] = px
		return True
p = list(map(int, input().split()))
gl = [[] for _ in range(n)]
for i in range(m):
	(x, y) = map(int, input().split())
	unite(x - 1, y - 1)
for c in range(n):
	ap = find(c)
	gl[ap].append(c)
g = 0
for sg in gl:
	temp = [p[index] - 1 for index in sg]
	newset = set(sg) & set(temp)
	g += len(newset)
print(g)


from collections import defaultdict

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		group_members = defaultdict(list)
		for member in range(self.n):
			group_members[self.find(member)].append(member)
		return group_members

	def __str__(self):
		return '\n'.join((f'{r}: {m}' for (r, m) in self.all_group_members().items()))

def slove():
	(N, M) = map(int, input().split())
	u = UnionFind(N)
	P = list(map(int, input().split()))
	for _ in range(M):
		(x, y) = map(int, input().split())
		u.union(x - 1, y - 1)
	ans = 0
	for (i, p) in enumerate(P):
		if p - 1 in u.members(i):
			ans += 1
	print(ans)

def slove2():
	(N, M) = map(int, input().split())
	P = list(map(int, input().split()))
	l = list(range(N + 1))

	def find(p):
		if l[p] == p:
			return p
		else:
			l[p] = find(l[p])
			return l[p]
	for _ in range(M):
		(x, y) = map(int, input().split())
		x = find(x)
		y = find(y)
		if x > y:
			(x, y) = (y, x)
		l[y] = find(x)
	ans = 0
	for (i, p) in enumerate(P):
		if find(i + 1) == find(p):
			ans += 1
	print(ans)

def __starting_point():
	slove2()
__starting_point()


(n, m) = map(int, input().split())
P = [i - 1 for i in list(map(int, input().split()))]

class UnionFind:

	def __init__(self, num):
		self.n = num
		self.parents = [-1 for i in range(self.n)]

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		xx = self.find(x)
		yy = self.find(y)
		if xx == yy:
			return
		else:
			size_xx = abs(self.parents[xx])
			size_yy = abs(self.parents[yy])
			if size_xx > size_yy:
				(xx, yy) = (yy, xx)
			self.parents[yy] += self.parents[xx]
			self.parents[xx] = yy

	def size(self, x):
		xx = self.find(x)
		return abs(self.parents[xx])

	def same(self, x, y):
		return 1 if self.find(x) == self.find(y) else 0

	def members(self, x):
		xx = self.find(x)
		return [i for i in range(self.n) if self.find(i) == xx]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def state_grouping(self):
		return list(self.all_group_members().values())
uf = UnionFind(n)
for i in range(m):
	(a, b) = map(int, input().split())
	a -= 1
	b -= 1
	uf.union(a, b)
ans = 0
for i in range(n):
	ans += uf.same(i, P[i])
print(ans)


from collections import deque
(n, m) = map(int, input().split())
plst = list(map(int, input().split()))
edges = [[] for _ in range(n)]
for _ in range(m):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	edges[x].append(y)
	edges[y].append(x)
check = [False for _ in range(n)]
uni = [0 for _ in range(n)]
pos = 0
queue = deque()
for i in range(n):
	if check[i]:
		continue
	pos += 1
	queue.append(i)
	check[i] = True
	while queue:
		now = queue.popleft()
		uni[now] += pos
		uni[plst[now] - 1] -= pos
		for aft in edges[now]:
			if check[aft]:
				continue
			check[aft] = True
			queue.append(aft)
print(uni.count(0))


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def all_group_members(self):
		return [set(self.members(r)) for r in self.roots()]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))

def main():
	(n, m) = list(map(int, input().split()))
	P = list([int(x) - 1 for x in input().split()])
	uf = UnionFind(n)
	for _ in range(m):
		(x, y) = [int(x) - 1 for x in input().split()]
		uf.union(x, y)
	ans = 0
	for (i, p) in enumerate(P):
		if uf.same(i, p):
			ans += 1
	print(ans)

def __starting_point():
	main()
__starting_point()


from collections import deque
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
g = [[] for i in range(n)]
for i in range(m):
	(a, b) = map(int, input().split())
	g[a - 1].append(b - 1)
	g[b - 1].append(a - 1)
v = [-1 for i in range(n)]
s = 0
for i in range(n):
	if v[i] != -1:
		continue
	s += 1
	v[i] = s
	d = deque([i])
	while len(d):
		x = d.popleft()
		for i in g[x]:
			if v[i] == -1:
				d.append(i)
				v[i] = s
ans = 0
for i in range(n):
	if v[i] == v[p[i] - 1]:
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.size = [1] * n

	def root(self, x):
		while self.parent[x] != x:
			self.parent[x] = self.parent[self.parent[x]]
			x = self.parent[x]
		return x

	def merge(self, x, y):
		(x, y) = (self.root(x), self.root(y))
		if x == y:
			return False
		if self.size[x] < self.size[y]:
			(x, y) = (y, x)
		self.size[x] += self.size[y]
		self.parent[y] = x
		return True

	def issame(self, x, y):
		return self.root(x) == self.root(y)

	def getsize(self, x):
		return self.size[self.root(x)]
import sys
readline = sys.stdin.readline
read = sys.stdin.read
(n, m) = list(map(int, readline().split()))
(*p,) = list(map(int, readline().split()))
UF = UnionFind(n)
for _ in range(m):
	(x, y) = list(map(int, readline().split()))
	UF.merge(x - 1, y - 1)
q = [set() for _ in range(n)]
r = [set() for _ in range(n)]
for i in range(n):
	v = UF.root(i)
	q[v].add(i)
	r[v].add(p[i] - 1)
ans = 0
for i in range(n):
	ans += len(q[i] & r[i])
print(ans)


import sys
import math
import collections
import bisect
import copy
import itertools
sys.setrecursionlimit(10 ** 7)
INF = 10 ** 16
MOD = 10 ** 9 + 7
ni = lambda : int(sys.stdin.readline().rstrip())
ns = lambda : list(map(int, sys.stdin.readline().rstrip().split()))
na = lambda : list(map(int, sys.stdin.readline().rstrip().split()))
na1 = lambda : list([int(x) - 1 for x in sys.stdin.readline().rstrip().split()])

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))

def main():
	(n, m) = ns()
	p = na1()
	uf = UnionFind(n)
	for _ in range(m):
		(x, y) = ns()
		uf.union(x - 1, y - 1)
	ans = 0
	for (i, pi) in enumerate(p):
		if uf.same(i, pi):
			ans += 1
	print(ans)

def __starting_point():
	main()
__starting_point()


class Unionfind:

	def __init__(self, N):
		self.N = N
		self.parents = [-1] * N

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def all_group_members(self):
		members_dict = {i: set([i]) for (i, x) in enumerate(self.parents) if x < 0}
		for (i, x) in enumerate(self.parents):
			if x >= 0:
				members_dict[self.find(x)].add(i)
		return members_dict
(n, m) = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = [list(map(int, input().split())) for _ in range(m)]
uf = Unionfind(n)
for (x, y) in xy:
	uf.union(x - 1, y - 1)
ans = 0
for lst in list(uf.all_group_members().values()):
	ans += sum((p[num] - 1 in lst for num in lst))
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def size(self, x):
		return -self.parents[self.find(x)]

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
uf = UnionFind(n)
for i in range(m):
	(x, y) = map(int, input().split())
	uf.unite(x - 1, y - 1)
ans = 0
for i in range(n):
	if uf.same(i, p[i] - 1):
		ans += 1
print(ans)


import sys
from collections import deque
input = sys.stdin.readline

def bfs(N, G, p):
	c_comp_p_list = []
	c_comp_i_list = []
	visited = [False] * N
	for i in range(N):
		if visited[i]:
			continue
		visited[i] = True
		c_comp_p_list.append([p[i]])
		c_comp_i_list.append(set([i + 1]))
		cc_p_add = c_comp_p_list[-1].append
		cc_i_add = c_comp_i_list[-1].add
		queue = deque(G[i])
		while queue:
			u = queue.popleft()
			if visited[u]:
				continue
			visited[u] = True
			cc_p_add(p[u])
			cc_i_add(u + 1)
			for v in G[u]:
				if visited[v]:
					continue
				queue.append(v)
	res = 0
	for (c_comp_p, c_comp_i) in zip(c_comp_p_list, c_comp_i_list):
		for pp in c_comp_p:
			if pp in c_comp_i:
				res += 1
	return res

def main():
	(N, M) = list(map(int, input().split()))
	p = tuple(map(int, input().split()))
	G = [[] for _ in range(N)]
	for _ in range(M):
		(x, y) = list(map(int, input().split()))
		x -= 1
		y -= 1
		G[x].append(y)
		G[y].append(x)
	ans = bfs(N, G, p)
	print(ans)

def __starting_point():
	main()
__starting_point()


from collections import deque
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
root = [[] for i in range(n)]
for _ in range(m):
	(a, b) = (int(x) for x in input().split())
	root[b - 1].append(a - 1)
	root[a - 1].append(b - 1)
check = [-1] * n
for j in range(n):
	if check[j] != -1:
		continue
	stack = deque([j])
	check[j] = j
	while len(stack) > 0:
		v = stack.popleft()
		for i in root[v]:
			if check[i] == -1:
				check[i] = j
				stack.append(i)
ans = 0
for (key, value) in enumerate(p):
	if check[key] == check[value - 1]:
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))

def main():
	(N, M) = map(int, input().split())
	P = list(map(int, input().split()))
	uni = UnionFind(N)
	for i in range(N):
		P[i] -= 1
	for _ in range(M):
		(x, y) = map(int, input().split())
		x -= 1
		y -= 1
		uni.union(x, y)
	ans = 0
	for i in range(N):
		if P[i] == i:
			ans += 1
		elif uni.same(i, P[i]):
			ans += 1
	print(ans)

def __starting_point():
	main()
__starting_point()


class UnionFind:

	def __init__(self, n: int):
		self.parent = [i for i in range(n + 1)]
		self.rank = [0] * (n + 1)

	def find(self, x: int) -> int:
		if self.parent[x] == x:
			return x
		else:
			self.parent[x] = self.find(self.parent[x])
			return self.parent[x]

	def unit(self, x: int, y: int):
		parent_x = self.find(x)
		parent_y = self.find(y)
		if self.rank[parent_x] < self.rank[parent_y]:
			self.parent[parent_x] = parent_y
		else:
			self.parent[parent_y] = parent_x
			if self.rank[parent_y] == self.rank[parent_x]:
				self.rank[parent_x] += 1

	def same_check(self, x: int, y: int) -> bool:
		return self.find(x) == self.find(y)
(N, M) = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = UnionFind(N)
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	xy.unit(x, y)
ans = 0
for i in range(N):
	if xy.same_check(p[i], i + 1):
		ans += 1
print(ans)


import sys
sys.setrecursionlimit(6500)

def find(n):
	if d[n] < 0:
		return n
	else:
		d[n] = find(d[n])
		return d[n]

def union(a, b):
	a = find(a)
	b = find(b)
	if a == b:
		return False
	if d[a] <= d[b]:
		d[a] += d[b]
		d[b] = a
	else:
		d[b] += d[a]
		d[a] = b
	return True

def members(n):
	p = find(n)
	ans = []
	for i in range(N):
		if find(i) == p:
			ans.append(i)
	return ans

def same(a, b):
	if find(a) == find(b):
		return True
	else:
		return False
(N, M) = map(int, input().split())
p = list(map(int, input().split()))
d = [-1] * N
for i in range(M):
	(x, y) = map(int, input().split())
	(x, y) = (x - 1, y - 1)
	union(x, y)
ans = 0
for i in range(N):
	if same(i, p[i] - 1):
		ans += 1
print(ans)


from collections import Counter, deque, defaultdict
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
idx_lst = [0] * n
for (i, x) in enumerate(p):
	idx_lst[x - 1] = i
lst = [[] for _ in range(n)]
for i in range(m):
	(x, y) = map(int, input().split())
	lst[x - 1].append(y - 1)
	lst[y - 1].append(x - 1)
seen = [False] * n
ans = 0
for i in range(n):
	if seen[i]:
		continue
	seen[i] = True
	q = deque([i])
	dic = defaultdict(int)
	dic[i] += 1
	while q:
		t = q.pop()
		for j in lst[t]:
			if seen[j]:
				continue
			seen[j] = True
			dic[j] += 1
			q.append(j)
	for k in list(dic.keys()):
		if dic[idx_lst[k]]:
			ans += 1
print(ans)


import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 7)

class UnionFindPathCompression:

	def __init__(self, n):
		self.parents = list(range(n))
		self.rank = [1] * n
		self.size = [1] * n

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return
		elif self.rank[px] < self.rank[py]:
			self.parents[px] = py
			self.size[py] += self.size[px]
		else:
			self.parents[py] = px
			self.size[px] += self.size[py]
			if self.rank[px] == self.rank[py]:
				self.rank[px] += 1
(n, m) = map(int, input().split())
P = list(map(int, input().split()))
ufpc = UnionFindPathCompression(n)
for i in range(m):
	(x, y) = map(int, input().split())
	(x, y) = (x - 1, y - 1)
	ufpc.union(x, y)
ans = 0
for (i, p) in enumerate(P):
	if ufpc.find(i) == ufpc.find(p - 1):
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(n, m) = map(int, input().split())
p = list(map(int, input().split()))
u = UnionFind(n)
for _ in range(m):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	u.union(x, y)
ans = 0
for i in range(n):
	pi = p[i]
	pi -= 1
	if u.same(i, pi):
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, num):
		self.parent = [i for i in range(num + 1)]

	def find(self, node):
		if self.parent[node] == node:
			return node
		self.parent[node] = self.find(self.parent[node])
		return self.parent[node]

	def union(self, node1, node2):
		node1 = self.find(node1)
		node2 = self.find(node2)
		if node1 == node2:
			return
		if self.parent[node1] > self.parent[node2]:
			(node1, node2) = (node2, node1)
		self.parent[node2] = node1
		return

	def same(self, node1, node2):
		return self.find(node1) == self.find(node2)
(n, m) = list(map(int, input().split()))
p = list(map(int, input().split()))
uf = UnionFind(n)
for _ in range(m):
	(x, y) = list(map(int, input().split()))
	x -= 1
	y -= 1
	uf.union(p[x], p[y])
ans = 0
for i in range(n):
	if p[i] == i + 1 or uf.same(p[i], i + 1):
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.par = [i for i in range(n)]
		self.rank = [0] * n
		self.members = [{i} for i in range(n)]
		self.roots = {i for i in range(n)}

	def root(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.root(self.par[x])
			return self.par[x]

	def union(self, x, y):
		rx = self.root(x)
		ry = self.root(y)
		if rx != ry:
			if self.rank[rx] < self.rank[ry]:
				self.par[rx] = ry
				self.members[ry] |= self.members[rx]
				self.roots.discard(rx)
			else:
				self.par[ry] = rx
				self.members[rx] |= self.members[ry]
				self.roots.discard(ry)
				if self.rank[rx] == self.rank[ry]:
					self.rank[rx] += 1

	def same(self, x, y):
		return self.root(x) == self.root(y)
(N, M) = list(map(int, input().split()))
P = list([int(x) - 1 for x in input().split()])
X = UnionFind(N)
Y = UnionFind(N)
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	x -= 1
	y -= 1
	X.union(x, y)
	Y.union(P[x], P[y])
ans = 0
roots = X.roots
for r in roots:
	A = X.members[r]
	B = Y.members[P[r]]
	ans += len(A & B)
print(ans)


import sys

def input():
	return sys.stdin.readline().strip()

def input_int():
	return int(input())

def input_int_list():
	return [int(i) for i in input().split()]

class UnionFind:

	def __init__(self, n: int):
		self.nodes = n
		self.parents = [-1] * n
		self.rank = [0] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.rank[x] < self.rank[y]:
			self.parents[y] += self.parents[x]
			self.parents[x] = y
		else:
			self.parents[x] += self.parents[y]
			self.parents[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1

	def get_size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def get_groups(self, index_base=0) -> list:
		d = {}
		for i in range(index_base, self.nodes):
			p = self.find(i)
			if p not in list(d.keys()):
				d[p] = set()
			d[p].add(i)
		return list(d.values())

def main():
	(n, m) = input_int_list()
	A = [None] + input_int_list()
	djs = UnionFind(n + 1)
	for _ in range(m):
		(x, y) = input_int_list()
		djs.unite(x, y)
	groups = djs.get_groups()
	ans = 0
	for group in groups:
		v = set()
		for i in group:
			v.add(A[i])
		ans += len(group & v)
	print(ans)
	return

def __starting_point():
	main()
__starting_point()


def find(x):
	if par[x] < 0:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	p = find(x)
	q = find(y)
	if p == q:
		return None
	if p > q:
		(p, q) = (q, p)
	par[p] += par[q]
	par[q] = p

def same(x, y):
	return find(x) == find(y)

def size(x):
	return -par[find(x)]
(n, m) = map(int, input().split())
par = [-1 for i in range(n)]
p = list(map(int, input().split()))
for i in range(m):
	(x, y) = map(int, input().split())
	unite(x - 1, y - 1)
ans = 0
for i in range(n):
	if same(p[i] - 1, i):
		ans += 1
print(ans)


import math, itertools, fractions, heapq, collections, bisect, sys, queue, copy
sys.setrecursionlimit(10 ** 7)
inf = 10 ** 20
mod = 10 ** 9 + 7
dd = [(-1, 0), (0, 1), (1, 0), (0, -1)]
ddn = [(-1, 0), (-1, 1), (0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1)]

def LI():
	return [int(x) for x in sys.stdin.readline().split()]

def I():
	return int(sys.stdin.readline())

def F():
	return float(sys.stdin.readline())

def LS():
	return sys.stdin.readline().split()

def S():
	return input()

class UnionFind:

	def __init__(self, sz):
		self.sz = sz
		self.data = [-1] * sz
		self.amount = [0] * sz

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return False
		self.amount[x] += self.amount[y]
		self.amount[y] += self.amount[x]
		if self.data[x] > self.data[y]:
			(x, y) = (y, x)
		self.data[x] += self.data[y]
		self.data[y] = x
		return True

	def find(self, k):
		if self.data[k] < 0:
			return k
		self.data[k] = self.find(self.data[k])
		return self.data[k]

	def size(self, k):
		return -self.data[self.find(k)]

	def set_amount(self, k, k_amount):
		self.amount[k] = k_amount

	def get_amount(self, k):
		return self.amount[k]

def main():
	(n, k) = LI()
	l = LI()
	d = {}
	uf = UnionFind(n)
	for (i, x) in enumerate(l):
		x -= 1
		d[i] = x
	for _ in range(k):
		(a, b) = LI()
		uf.unite(a - 1, b - 1)
	ans = 0
	for x in l:
		x -= 1
		if uf.find(x) == uf.find(d[x]):
			ans += 1
	return ans
print(main())


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self):
		ret = dict()
		for i in range(self.n):
			x = self.find(i)
			if x in ret:
				ret[x].add(i)
			else:
				ret[x] = {i}
		return ret
(N, M) = map(int, input().split())
p = list(map(int, input().split()))
uf = UnionFind(N)
for _ in range(M):
	(x, y) = map(int, input().split())
	uf.union(x - 1, y - 1)
ans = 0
for id_s in uf.members().values():
	val_s = set()
	for i in id_s:
		val_s.add(p[i] - 1)
	ans += len(id_s & val_s)
print(ans)


def find(x):
	if par[x] == x:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def same(x, y):
	return find(x) == find(y)

def unite(x, y):
	x = find(x)
	y = find(y)
	if x == y:
		return 0
	par[x] = y
	size[y] = size[x] + size[y]
	size[x] = 0
(N, M) = list(map(int, input().split()))
plist = list(map(int, input().split()))
ABs = [list(map(int, input().split())) for _ in range(M)]
par = [i for i in range(N + 1)]
size = [1 for _ in range(N + 1)]
for AB in ABs:
	unite(AB[0], AB[1])
Ans = 0
for i in range(len(plist)):
	if plist[i] == i + 1:
		Ans += 1
	elif same(plist[i], i + 1):
		Ans += 1
print(Ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def num_roots(self):
		return len([i for (i, x) in enumerate(self.parents) if x < 0])

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def num_members(self, x):
		return abs(self.parents[self.find(x)])

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = list(map(int, input().split()))
P = list(map(int, input().split()))
uf = UnionFind(N)
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	uf.union(x - 1, y - 1)
from collections import defaultdict
d = defaultdict(lambda : [])
for i in range(N):
	d[uf.find(i)].append(i)
from bisect import bisect_left

def binary_search(A, p):
	if A[0] <= p and p <= A[-1]:
		if p == A[bisect_left(A, p)]:
			return True
	return False
ans = 0
for v in list(d.values()):
	lis = sorted(v)
	for a in v:
		if binary_search(lis, P[a] - 1):
			ans += 1
print(ans)


import sys
stdin = sys.stdin
sys.setrecursionlimit(10 ** 6)
ni = lambda : int(ns())
na = lambda : list(map(int, stdin.readline().split()))
nn = lambda : list(stdin.readline().split())
ns = lambda : stdin.readline().rstrip()
import collections
import itertools
import operator

class UnionFind:

	def __init__(self, elems=None):

		class KeyDict(dict):

			def __missing__(self, key):
				self[key] = key
				return key
		self.parent = KeyDict()
		self.rank = collections.defaultdict(int)
		self.size_ = collections.defaultdict(lambda : 1)
		if elems is not None:
			for elem in elems:
				(_, _, _) = (self.parent[elem], self.rank[elem], self.size_[elem])

	def find(self, x):
		if self.parent[x] == x:
			return x
		else:
			self.parent[x] = self.find(self.parent[x])
			return self.parent[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.rank[x] < self.rank[y]:
			self.parent[x] = y
			self.size_[y] += self.size_[x]
		else:
			self.parent[y] = x
			self.size_[x] += self.size_[y]
		if self.rank[x] == self.rank[y]:
			self.rank[x] += 1

	def are_same(self, x, y):
		return self.find(x) == self.find(y)

	def grouper(self):
		roots = [(x, self.find(x_par)) for (x, x_par) in self.parent.items()]
		root = operator.itemgetter(1)
		for (_, group) in itertools.groupby(sorted(roots, key=root), root):
			yield [x for (x, _) in group]

	def size(self, x):
		return self.size_[self.find(x)]
(n, m) = na()
p = na()
uf = UnionFind()
for i in range(m):
	(x, y) = na()
	uf.unite(x, y)
dp = []
for i in range(n):
	dp.append(uf.find(i + 1))
ans = 0
for i in range(n):
	if dp[i] == uf.find(p[i]) or i + 1 == p[i]:
		ans += 1
print(ans)


import bisect, collections, copy, heapq, itertools, math, string, sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(10 ** 7)
INF = float('inf')

def I():
	return int(input())

def F():
	return float(input())

def SS():
	return input()

def LI():
	return [int(x) for x in input().split()]

def LI_():
	return [int(x) - 1 for x in input().split()]

def LF():
	return [float(x) for x in input().split()]

def LSS():
	return input().split()

def resolve():
	(N, M) = LI()
	p = LI_()
	G = [[] for _ in range(N)]
	for _ in range(M):
		(x, y) = LI_()
		G[x].append(y)
		G[y].append(x)
	visited = [False] * N

	def dfs(c, tmp):
		visited[c] = True
		tmp.append(c)
		for n in G[c]:
			if not visited[n]:
				dfs(n, tmp)
	c = []
	for i in range(N):
		if not visited[i]:
			tmp = []
			dfs(i, tmp)
			c.append(tmp)
	ans = sum([len({p[j] for j in i} & set(i)) for i in c])
	print(ans)

def __starting_point():
	resolve()
__starting_point()


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = map(int, input().split())
Ps = [0] + list(map(int, input().split()))
uf = UnionFind(N + 1)
for _ in range(M):
	(x, y) = map(int, input().split())
	uf.union(x, y)
rlt = 0
for i in range(1, N + 1):
	if uf.find(i) == uf.find(Ps[i]):
		rlt += 1
print(rlt)


(N, M) = list(map(int, input().split()))
p = list(map(int, input().split()))
pairs = [list(map(int, input().split())) for _ in range(M)]

class UnionFind:

	def __init__(self, n):
		self.par = [i for i in range(n + 1)]

	def root(self, x):
		if self.par[x] == x:
			return x
		self.par[x] = self.root(self.par[x])
		return self.par[x]

	def union(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return
		self.par[x] = y

	def check(self, x, y):
		return self.root(x) == self.root(y)
u = UnionFind(N)
for (x, y) in pairs:
	u.union(x, y)
ans = 0
for j in range(1, N + 1):
	if u.check(p[j - 1], j):
		ans += 1
print(ans)


def read_values():
	return list(map(int, input().split()))

def read_index():
	return [int(x) - 1 for x in input().split()]

def read_list():
	return list(read_values())

def read_lists(N):
	return [read_list() for n in range(N)]

class UF:

	def __init__(self, N):
		self.state = [-1] * N
		self.rank = [0] * N
		self.num_group = N

	def get_parent(self, a):
		p = self.state[a]
		if p < 0:
			return a
		q = self.get_parent(p)
		self.state[a] = q
		return q

	def make_pair(self, a, b):
		pa = self.get_parent(a)
		pb = self.get_parent(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			(pa, pb) = (pb, pa)
			(a, b) = (b, a)
		elif self.rank[pa] == self.rank[pb]:
			self.rank[pb] += 1
		self.state[pb] += self.state[pa]
		self.state[pa] = pb
		self.state[a] = pb
		self.num_group -= 1

	def is_pair(self, a, b):
		return self.get_parent(a) == self.get_parent(b)

	def get_size(self, a):
		return -self.state[self.get_parent(a)]
(N, M) = read_values()
A = read_list()
uf = UF(N)
for _ in range(M):
	(i, j) = read_index()
	uf.make_pair(A[i] - 1, A[j] - 1)
res = 0
for (i, a) in enumerate(A):
	if uf.is_pair(i, A[i] - 1):
		res += 1
print(res)


class UnionFind(object):

	def __init__(self, n=1):
		self.par = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]
		self.size = [1 for _ in range(n)]

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				(x, y) = (y, x)
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1
			self.par[y] = x
			self.size[x] += self.size[y]

	def is_same(self, x, y):
		return self.find(x) == self.find(y)

	def get_size(self, x):
		x = self.find(x)
		return self.size[x]
(N, M) = map(int, input().split())
p = list(map(int, input().split()))
uf = UnionFind(N)
for i in range(M):
	(x, y) = map(int, input().split())
	uf.union(p[x - 1] - 1, p[y - 1] - 1)
ans = 0
for i in range(N):
	if uf.is_same(p[i] - 1, i):
		ans += 1
print(ans)


ma = lambda : map(int, input().split())
lma = lambda : list(map(int, input().split()))
ni = lambda : int(input())
yn = lambda fl: print('Yes') if fl else print('No')
import collections
import math
import itertools
import heapq as hq

class unionfind:

	def __init__(self, n):
		self.par = list(range(n))
		self.size = [1] * n
		self.rank = [0] * n

	def root(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.root(self.par[x])
			return self.par[x]

	def same(self, x, y):
		return self.root(x) == self.root(y)

	def unite(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return
		else:
			if self.rank[x] < self.rank[y]:
				(x, y) = (y, x)
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1
			self.par[y] = x
			self.size[x] += self.size[y]

	def get_size(self, x):
		x = self.root(x)
		return self.size[x]
(n, m) = ma()
P = lma()
uf = unionfind(n + 1)
for i in range(m):
	(x, y) = ma()
	uf.unite(x, y)
ans = 0
for i in range(n):
	if uf.same(i + 1, P[i]):
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.par = [i for i in range(n + 1)]
		self.rank = [0] * (n + 1)

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if self.rank[x] < self.rank[y]:
			self.par[x] = y
		else:
			self.par[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1

	def same_check(self, x, y):
		return self.find(x) == self.find(y)
(N, M) = list(map(int, input().split()))
S = list(map(int, input().split()))
ans = 0
TA = []
TB = []
for i in range(M):
	(a, b) = list(map(int, input().split()))
	TA.append(a)
	TB.append(b)
uni = UnionFind(N)
for i in range(M):
	uni.union(TA[i], TB[i])
for i in range(N):
	if uni.same_check(i + 1, S[i]) == True:
		ans += 1
print(ans)


from collections import defaultdict

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)
(N, M) = list(map(int, input().split()))
uf = UnionFind(N)
p = list(map(int, input().split()))
for _ in range(M):
	(x, y) = list(map(int, input().split()))
	x -= 1
	y -= 1
	uf.union(x, y)
ans = 0
for i in range(N):
	if uf.same(i, p[i] - 1):
		ans += 1
print(ans)


from collections import defaultdict, deque
import sys, heapq, bisect, math, itertools, string, queue, datetime

def inpl():
	return list(map(int, input().split()))

def inpl_s():
	return list(input().split())

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = map(int, input().split())
p = inpl()
uf = UnionFind(N)
for i in range(M):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	uf.union(x, y)
ans = 0
for i in range(N):
	if uf.same(p[i] - 1, i):
		ans += 1
print(ans)


(n, m) = map(int, input().split())
(*p,) = map(int, input().split())
p = [z - 1 for z in p]
es = [[] for _ in range(n)]
for _ in range(m):
	(x, y) = map(int, input().split())
	es[x - 1].append(y - 1)
	es[y - 1].append(x - 1)
group = [-1] * n
last = -1
for i in range(n):
	if group[i] == -1:
		last += 1
		group[i] = last
		stack = [i]
		while stack:
			j = stack.pop()
			for e in es[j]:
				if group[e] == -1:
					stack.append(e)
					group[e] = last
groupset = set(group)
group1 = [[] for g in groupset]
group2 = [[] for g in groupset]
for i in range(n):
	group1[group[i]].append(i)
	group2[group[i]].append(p[i])
ans = 0
for g in groupset:
	ans += len(set(group1[g]) & set(group2[g]))
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.root = [-1] * (n + 1)
		self.rnk = [0] * (n + 1)

	def find(self, x):
		if self.root[x] < 0:
			return x
		else:
			self.root[x] = self.find(self.root[x])
			return self.root[x]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		elif self.rnk[x] > self.rnk[y]:
			self.root[x] += self.root[y]
			self.root[y] = x
		else:
			self.root[y] += self.root[x]
			self.root[x] = y
			if self.rnk[x] == self.rnk[y]:
				self.rnk[y] += 1

	def same(self, x, y):
		return self.find(x) == self.find(y)
(n, m) = map(int, input().split())
p = [0] + list(map(int, input().split()))
uf = UnionFind(n)
for _ in range(m):
	(a, b) = map(int, input().split())
	uf.unite(a, b)
cnt = 0
for (i, j) in enumerate(p):
	if uf.same(i, j):
		cnt += 1
print(cnt - 1)


(n, m) = list(map(int, input().split()))
a = list(map(int, input().split()))
s = [[] for i in range(n)]
for i in range(m):
	inp = list(map(int, input().split()))
	s[inp[0] - 1].append(inp[1] - 1)
	s[inp[1] - 1].append(inp[0] - 1)
c = 0
d = [0 for i in range(n)]
for i in range(n):
	if d[i]:
		continue
	c += 1
	d[i] = c
	st = s[i]
	while st:
		ns = []
		for j in st:
			if d[j]:
				continue
			d[j] = c
			ns += s[j]
		st = ns
c = 0
for i in range(n):
	if d[i] == d[a[i] - 1]:
		c += 1
print(c)


(N, M) = map(int, input().split())
p = [0] + list(map(int, input().split()))
xy = [list(map(int, input().split())) for i in range(M)]
li = [[] for i in range(N + 1)]
for i in range(M):
	li[xy[i][0]].append(xy[i][1])
	li[xy[i][1]].append(xy[i][0])
lis = [0] * (N + 1)
ma = 0
for i in range(1, N + 1):
	if lis[i] == 0:
		deque = [i]
		lis[i] = i
		ma = i
		while deque:
			x = deque.pop(0)
			for j in li[x]:
				if lis[j] == 0:
					lis[j] = i
					deque.append(j)
lit = [[] for i in range(ma)]
lif = [[] for i in range(ma)]
for i in range(1, N + 1):
	lit[lis[i] - 1].append(i)
	lif[lis[i] - 1].append(p[i])
ans = 0
for i in range(ma):
	ans += len(set(lit[i]) & set(lif[i]))
print(ans)


class UnionFindTree:

	def __init__(self, n):
		self.nodes = [-1] * n

	def find(self, i):
		if self.nodes[i] < 0:
			return i
		else:
			self.nodes[i] = self.find(self.nodes[i])
			return self.nodes[i]

	def union(self, i, j):
		i = self.find(i)
		j = self.find(j)
		if i == j:
			return
		if self.nodes[i] > self.nodes[j]:
			(i, j) = (j, i)
		self.nodes[i] += self.nodes[j]
		self.nodes[j] = i

	def size(self, i):
		i = self.find(i)
		return -self.nodes[i]
(n, m) = list(map(int, input().split()))
p = list([int(x) - 1 for x in input().split()])
uft = UnionFindTree(n)
for _ in range(m):
	(x, y) = [int(x) - 1 for x in input().split()]
	uft.union(x, y)
ans = 0
for i in range(n):
	if uft.find(p[i]) == uft.find(i):
		ans += 1
print(ans)


(n, m) = map(int, input().split())
P = [int(i) for i in input().split()]
uf = [i for i in range(n + 1)]

def ufuf(x):
	while x != uf[x]:
		x = uf[x]
	return x
for i in range(m):
	(x, y) = map(int, input().split())
	if ufuf(x) < ufuf(y):
		uf[ufuf(y)] = ufuf(x)
	else:
		uf[ufuf(x)] = ufuf(y)
ans = 0
for i in range(1, n + 1):
	if ufuf(i) == ufuf(P[i - 1]):
		ans += 1
print(ans)


import sys

def input():
	return sys.stdin.readline().strip()

def mapint():
	return map(int, input().split())
sys.setrecursionlimit(10 ** 9)
(N, M) = mapint()
Ps = [p - 1 for p in list(mapint())]

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]
uf = UnionFind(N)
for _ in range(M):
	(x, y) = mapint()
	uf.union(x - 1, y - 1)
roots = uf.roots()
root_set = [set() for _ in range(N)]
for i in range(N):
	root_set[uf.find(i)].add(i)
ans = 0
for i in range(N):
	p = Ps[i]
	if p in root_set[uf.find(i)]:
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, N):
		self.par = [i for i in range(N)]
		self.rank = [0 for _ in range(N)]
		self.size = [1 for _ in range(N)]

	def unite(self, x, y):
		x = self.getroot(x)
		y = self.getroot(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				(x, y) = (y, x)
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1
			self.par[y] = x
			self.size[x] += self.size[y]

	def united(self, x, y):
		return self.getroot(x) == self.getroot(y)

	def getroot(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.getroot(self.par[x])
			return self.par[x]

	def getsize(self, x):
		return self.size[self.getroot(x)]
(N, M) = map(int, input().split())
UF = UnionFind(N + 1)
p = [0] + list(map(int, input().split()))
for _ in range(M):
	(x, y) = map(int, input().split())
	UF.unite(x, y)
print(sum([1 for i in range(1, N + 1) if UF.getroot(i) == UF.getroot(p[i])]))


(N, M) = map(int, input().split())
(*P,) = map(int, input().split())
xy = [list(map(int, input().split())) for _ in range(M)]
R = [-1] * (N + 1)

def root(x):
	while R[x] >= 0:
		x = R[x]
	return x

def union(x, y):
	x = root(x)
	y = root(y)
	if x == y:
		return
	if R[x] > R[y]:
		(x, y) = (y, x)
	R[x] += R[y]
	R[y] = x
for (x, y) in xy:
	union(x, y)
ans = sum((root(i + 1) == root(P[i]) for i in range(N)))
print(ans)


import sys
input = sys.stdin.readline

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def all_group_members(self):
		d = {root: [] for root in self.roots()}
		for i in range(self.n):
			d[self.find(i)].append(i)
		return d

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = [list(map(int, input().split())) for _ in range(M)]
uf = UnionFind(N)
for (x, y) in xy:
	x -= 1
	y -= 1
	uf.union(x, y)
ans = 0
for renketu_seibun in list(uf.all_group_members().values()):
	can_reach = set([p[v] - 1 for v in renketu_seibun])
	for v in renketu_seibun:
		ans += v in can_reach
print(ans)


(n, m) = map(int, input().split())
p = [[0]] + [[int(i)] for i in input().split()]
q = [[i] for i in range(n + 1)]
par = [i for i in range(n + 1)]

def find(x):
	if x == par[x]:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	(x, y) = (find(x), find(y))
	if x > y:
		(x, y) = (y, x)
	if x != y:
		par[y] = x
		p[x] += p[y]
		q[x] += q[y]
for _ in range(m):
	(a, b) = map(int, input().split())
	unite(a, b)
for i in range(n):
	find(i)
ans = -1
for i in set(par):
	ans += len(set(p[i]) & set(q[i]))
print(ans)


import sys

def input():
	return sys.stdin.readline().strip()

class DisjointSet:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def size(self, x):
		return -self.parents[self.find(x)]
(N, M) = list(map(int, input().split()))
P = list([int(x) - 1 for x in input().split()])
ds = DisjointSet(N)
for _ in range(M):
	(x, y) = [int(x) - 1 for x in input().split()]
	ds.union(x, y)
print(sum((ds.same(P[i], i) for i in range(N))))


(n, m) = list(map(int, input().split()))
p = list(map(int, input().split()))
from collections import defaultdict
from collections import deque
c = 0
for i in range(n):
	if p[i] == i + 1:
		c += 1
vis = [0] * n

def dfs(x):
	vis[x] = 1
	a.add(x + 1)
	di = deque()
	di.append(x)
	while di:
		now = di.popleft()
		for j in d[now]:
			if not vis[j]:
				vis[j] = 1
				a.add(j + 1)
				di.append(j)
	for u in d[x]:
		if vis[u] == 0:
			dfs(u)
d = defaultdict(list)
for i in range(m):
	(a, b) = list(map(int, input().split()))
	d[a - 1].append(b - 1)
	d[b - 1].append(a - 1)
ans = 0
for i in range(n):
	if vis[i] == 0:
		a = set()
		dfs(i)
		l = 0
		z = 0
		for j in a:
			if p[j - 1] in a:
				z += 1
			if p[j - 1] == j:
				l += 1
		ans = max(ans, c + z - l)
print(ans)


import sys
input = sys.stdin.readline
(N, M) = map(int, input().split())
P = list(map(int, input().split()))
edges = [[] for _ in range(N)]
for _ in range(M):
	(x, y) = map(int, input().split())
	edges[x - 1].append(y - 1)
	edges[y - 1].append(x - 1)
ans = 0
visited = set()
for i in range(N):
	q = [i]
	loop = set()
	values = set()
	while q:
		x = q.pop()
		if x in visited:
			continue
		visited.add(x)
		loop.add(x + 1)
		values.add(P[x])
		for nx in edges[x]:
			if nx not in visited:
				q.append(nx)
	ans += len(loop & values)
print(ans)


from collections import Counter

class Unionfind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * (n + 1)

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}:{}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = map(int, input().split())
p = list(map(int, input().split()))
uf = Unionfind(N)
for i in range(M):
	(x, y) = map(int, input().split())
	uf.union(x - 1, y - 1)
cnt = sum((uf.same(p[i] - 1, i) for i in range(N)))
print(cnt)


import sys

def input():
	return sys.stdin.readline().rstrip()

class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n + 1)]
		self.rank = [0] * (n + 1)

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if self.rank[x] < self.rank[y]:
			self.parents[x] = y
		else:
			self.parents[y] = x
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1

	def same(self, x, y):
		return self.find(x) == self.find(y)

def main():
	(N, M) = list(map(int, input().split()))
	P = list([int(x) - 1 for x in input().split()])
	XY = [list([int(x) - 1 for x in input().split()]) for _ in range(M)]
	value_to_index = [0] * N
	for (i, p) in enumerate(P):
		value_to_index[p] = i
	uf = UnionFind(N)
	for (x, y) in XY:
		uf.union(x, y)
	ans = 0
	for i in range(N):
		if uf.find(i) == uf.find(value_to_index[i]):
			ans += 1
	print(ans)

def __starting_point():
	main()
__starting_point()


from collections import deque
(N, M) = map(int, input().split())
P = list(map(int, input().split()))
P.insert(0, 0)
G = {i: [] for i in range(1, N + 1)}
for _ in range(M):
	(x, y) = map(int, input().split())
	G[x].append(y)
	G[y].append(x)
col = [-1 for _ in range(N + 1)]
cnt = 0
for i in range(1, N + 1):
	if col[i] < 0:
		col[i] = cnt
		que = deque([i])
		while que:
			x = que.popleft()
			for y in G[x]:
				if col[y] < 0:
					col[y] = cnt
					que.append(y)
		cnt += 1
C = {c: [] for c in range(cnt)}
for i in range(1, N + 1):
	C[col[i]].append(i)
B = {c: [] for c in range(cnt)}
for c in C:
	for i in C[c]:
		B[c].append(P[i])
ans = 0
for c in C:
	a = set(C[c])
	b = set(B[c])
	ans += len(a & b)
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.root = [-1] * (n + 1)
		self.rnk = [0] * (n + 1)

	def find_root(self, x):
		if self.root[x] < 0:
			return x
		else:
			self.root[x] = self.find_root(self.root[x])
			return self.root[x]

	def unite(self, x, y):
		x = self.find_root(x)
		y = self.find_root(y)
		if x == y:
			return
		elif self.rnk[x] > self.rnk[y]:
			self.root[x] += self.root[y]
			self.root[y] = x
		else:
			self.root[y] += self.root[x]
			self.root[x] = y
			if self.rnk[x] == self.rnk[y]:
				self.rnk[y] += 1

	def is_same_group(self, x, y):
		return self.find_root(x) == self.find_root(y)

	def count(self, x):
		return -self.root[self.find_root(x)]
f = lambda : map(int, input().split())
(N, M) = f()
uf = UnionFind(N + 1)
p = list(f())
p_index = [[] for _ in [0] * (N + 1)]
for i in range(1, N + 1):
	p_index[p[i - 1]] = i
for _ in [0] * M:
	uf.unite(*f())
index_list = [[] for _ in [0] * (N + 1)]
group_list = [[] for _ in [0] * (N + 1)]
for i in range(1, N + 1):
	index_list[uf.find_root(i)].append(p_index[i])
	group_list[uf.find_root(i)].append(i)
res = 0
for i in range(1, N + 1):
	if i == uf.find_root(i):
		res += len(set(index_list[i]) & set(group_list[i]))
print(res)


import bisect
import heapq
import itertools
import sys
import math
import random
import time
from collections import Counter, deque, defaultdict
from functools import reduce
from operator import xor
from types import FunctionType
from typing import List
mod = 10 ** 9 + 7
sys.setrecursionlimit(10 ** 9)

def lmi():
	return list(map(int, input().split()))

def narray(*shape, init=0):
	if shape:
		num = shape[0]
		return [narray(*shape[1:], init=init) for _ in range(num)]
	return init

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		for i in range(self.n):
			if self.find(i) == root:
				yield i

	def roots(self):
		for (i, x) in enumerate(self.parents):
			if x < 0:
				yield i

	def group_count(self):
		return len(list(self.roots()))

	def all_group_members(self):
		ret = defaultdict(list)
		for i in range(self.n):
			root = self.find(i)
			ret[root].append(i)
		return ret

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, list(members)) for (r, members) in self.all_group_members()))

def main():
	(N, M) = lmi()
	P = lmi()
	XY = [lmi() for _ in range(M)]
	uf = UnionFind(N)
	for (x, y) in XY:
		(x, y) = (x - 1, y - 1)
		uf.union(P[x] - 1, P[y] - 1)
	ans = 0
	for i in range(N):
		ans += uf.same(P[i] - 1, i)
	print(ans)

def __starting_point():
	main()
__starting_point()


class UnionFind:

	def __init__(self, n):
		self.N = n
		self.parent = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]

	def root(self, x):
		visited_nodes = []
		while True:
			p = self.parent[x]
			if p == x:
				for node in visited_nodes:
					self.parent[node] = x
				return x
			else:
				visited_nodes.append(x)
				x = p

	def unite(self, x, y):
		if not self.root(x) == self.root(y):
			if self.rank[x] > self.rank[y]:
				self.parent[self.root(y)] = self.root(x)
			else:
				self.parent[self.root(x)] = self.root(y)
				if self.rank[x] == self.rank[y]:
					self.rank[self.root(y)] += 1

	def ifSame(self, x, y):
		return self.root(x) == self.root(y)

	def printDebugInfo(self):
		print([self.root(i) for i in range(self.N)])
(N, M) = list(map(int, input().split()))
P = [int(x) for x in input().split()]
tree = UnionFind(N)
for _ in range(M):
	(X, Y) = list(map(int, input().split()))
	tree.unite(X - 1, Y - 1)
count = 0
for i in range(N):
	if tree.ifSame(P[i] - 1, i):
		count += 1
print(count)


(n, m) = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = [list(map(int, input().split())) for _ in range(m)]
from collections import defaultdict

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		group_members = defaultdict(list)
		for member in range(self.n):
			group_members[self.find(member)].append(member)
		return group_members

	def __str__(self):
		return '\n'.join((f'{r}: {m}' for (r, m) in list(self.all_group_members().items())))
uf = UnionFind(n)
for i in xy:
	uf.union(i[0] - 1, i[1] - 1)
ans = 0
for i in range(n):
	if uf.same(i, p[i] - 1):
		ans += 1
print(ans)


class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(n, m) = list(map(int, input().split()))
uf = UnionFind(n)
p = list(map(int, input().split()))
for _ in range(m):
	(a, b) = list(map(int, input().split()))
	a -= 1
	b -= 1
	uf.union(a, b)
pp = [set() for _ in range(n)]
qq = [set() for _ in range(n)]
for i in range(n):
	r = uf.find(i)
	pp[r].add(i)
	qq[r].add(p[i] - 1)
ans = 0
for i in range(n):
	ans += len(pp[i] & qq[i])
print(ans)


(n, m) = map(int, input().split())
p = [int(i) for i in input().split()]
par = [i for i in range(n)]

def find(x):
	if x == par[x]:
		return x
	else:
		par[x] = find(par[x])
		return par[x]

def unite(x, y):
	(x, y) = (find(x), find(y))
	if x > y:
		(x, y) = (y, x)
	if x != y:
		par[y] = x
for _ in range(m):
	(a, b) = map(int, input().split())
	unite(a - 1, b - 1)
for i in range(n):
	find(i)
print(sum((find(i) == find(p[i] - 1) for i in range(n))))


import sys
import queue
input_methods = ['clipboard', 'file', 'key']
using_method = 0
input_method = input_methods[using_method]
tin = lambda : map(int, input().split())
lin = lambda : list(tin())
mod = 1000000007

def main():
	(n, m) = tin()
	al = [-1] + lin()
	bb = [[] for _ in range(n + 1)]
	for _ in range(m):
		(a, b) = tin()
		bb[a].append(b)
		bb[b].append(a)
	ll = []
	is_open = [0] * (n + 1)
	for i in range(n + 1):
		q = queue.Queue()
		q.put(i)
		t = []
		while not q.empty():
			pp = q.get()
			if is_open[pp] != 0:
				continue
			is_open[pp] = 1
			t.append(pp)
			for v in bb[pp]:
				q.put(v)
		ll.append(t)
	ret = 0
	for t in ll:
		st = set(t)
		for v in t:
			if al[v] in st:
				ret += 1
	print(ret)
isTest = False

def pa(v):
	if isTest:
		print(v)

def input_clipboard():
	import clipboard
	input_text = clipboard.get()
	input_l = input_text.splitlines()
	for l in input_l:
		yield l

def __starting_point():
	if sys.platform == 'ios':
		if input_method == input_methods[0]:
			ic = input_clipboard()
			input = lambda : ic.__next__()
		elif input_method == input_methods[1]:
			sys.stdin = open('inputFile.txt')
		else:
			pass
		isTest = True
	else:
		pass
	ret = main()
	if ret is not None:
		print(ret)
__starting_point()


class UnionFind(object):

	def __init__(self, n=1):
		self.par = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				(x, y) = (y, x)
			if self.rank[x] == self.rank[y]:
				self.rank[x] += 1
			self.par[y] = x

	def is_same(self, x, y):
		return self.find(x) == self.find(y)
(n, m) = map(int, input().split())
uf1 = UnionFind(n)
p = list(map(int, input().split()))
for i in range(m):
	(a, b) = map(int, input().split())
	uf1.union(a - 1, b - 1)
for i in range(n):
	uf1.find(i)
ans = 0
for i in range(n):
	if uf1.par[i] == uf1.par[p[i] - 1]:
		ans += 1
print(ans)


(N, M) = list(map(int, input().split()))
p_list = list(map(int, input().split()))
queries = [list(map(int, input().split())) for i in range(M)]
paths = [[] for i in range(N + 1)]
for (a, b) in queries:
	paths[a].append(b)
	paths[b].append(a)
groups = []
visited = [False] * (N + 1)
for start in range(N + 1):
	if visited[start] == True:
		continue
	queue = [start]
	t_group = set()
	t_group.add(start)
	visited[start] = True
	while queue:
		now = queue.pop()
		for next in paths[now]:
			if visited[next] == True:
				continue
			queue.append(next)
			t_group.add(next)
			visited[next] = True
	groups.append(t_group)
result = 0
for group in groups[1:]:
	result += sum((1 for m in group if p_list[m - 1] in group))
print(result)


class Union_Find:

	def __init__(self, N):
		self.n = N
		self.parents = [-1] * N
		self.rank = [0] * N

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.rank[x] > self.rank[y]:
			self.parents[x] += self.parents[y]
			self.parents[y] = x
		else:
			self.parents[y] += self.parents[x]
			self.parents[x] = y
			if self.rank[x] == self.rank[y]:
				self.rank[y] += 1

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return {r: self.members(r) for r in self.roots()}

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))
(N, M) = map(int, input().split())
P = list(map(lambda x: int(x) - 1, input().split()))
U = Union_Find(N)
for _ in range(M):
	(a, b) = map(int, input().split())
	U.union(a - 1, b - 1)
K = 0
for x in range(N):
	K += U.same(x, P[x])
print(K)


class Uf:

	def __init__(self, N):
		self.p = list(range(N))
		self.rank = [0] * N
		self.size = [1] * N

	def root(self, x):
		if self.p[x] != x:
			self.p[x] = self.root(self.p[x])
		return self.p[x]

	def same(self, x, y):
		return self.root(x) == self.root(y)

	def unite(self, x, y):
		u = self.root(x)
		v = self.root(y)
		if u == v:
			return
		if self.rank[u] < self.rank[v]:
			self.p[u] = v
			self.size[v] += self.size[u]
			self.size[u] = 0
		else:
			self.p[v] = u
			self.size[u] += self.size[v]
			self.size[v] = 0
			if self.rank[u] == self.rank[v]:
				self.rank[u] += 1

	def count(self, x):
		return self.size[self.root(x)]
(N, M) = map(int, input().split())
uf = Uf(N)
P = list(map(int, input().split()))
P = [i - 1 for i in P]
for i in range(M):
	(x, y) = map(int, input().split())
	x -= 1
	y -= 1
	uf.unite(x, y)
ans = 0
for i in range(N):
	if uf.root(P[i]) == uf.root(i):
		ans += 1
print(ans)


import math
import itertools
import queue
import bisect
from collections import deque, defaultdict
import heapq as hpq
from sys import stdin, setrecursionlimit
ipt = stdin.readline
setrecursionlimit(10 ** 7)
mod = 10 ** 9 + 7
dir = [(-1, 0), (0, -1), (1, 0), (0, 1)]
alp = 'abcdefghijklmnopqrstuvwxyz'

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = [-1] * n

	def find(self, x):
		if self.parents[x] < 0:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

	def size(self, x):
		return -self.parents[self.find(x)]

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def members(self, x):
		root = self.find(x)
		return set([i for i in range(self.n) if self.find(i) == root])

	def roots(self):
		return [i for (i, x) in enumerate(self.parents) if x < 0]

	def group_count(self):
		return len(self.roots())

	def all_group_members(self):
		return [self.members(r) for r in self.roots()]

	def __str__(self):
		return '\n'.join(('{}: {}'.format(r, self.members(r)) for r in self.roots()))

def main():
	(n, m) = list(map(int, ipt().split()))
	p = [int(i) - 1 for i in ipt().split()]
	uf = UnionFind(n)
	for i in range(m):
		(x, y) = list(map(int, ipt().split()))
		uf.union(x - 1, y - 1)
	ans = 0
	for i in range(n):
		if uf.same(i, p[i]):
			ans += 1
	print(ans)
	return None

def __starting_point():
	main()
__starting_point()


(n, m) = map(int, input().split())
pn = list(map(lambda x: int(x) - 1, input().split()))
ls = [-1] * n
for i in pn:
	ls[pn[i]] = i
par = [i for i in range(n)]

def find(x):
	if par[x] == x:
		return x
	else:
		s = find(par[x])
		par[x] = s
		return s

def unite(x, y):
	s = find(x)
	t = find(y)
	if s > t:
		par[s] = t
	else:
		par[t] = s
for _ in range(m):
	(x, y) = map(lambda x: int(x) - 1, input().split())
	unite(ls[x], ls[y])
dic = {}
for i in range(n):
	a = find(i)
	if a in dic:
		dic[a].add(ls[i])
	else:
		dic[a] = set([ls[i]])
ans = 0
for i in range(n):
	if i in dic[find(i)]:
		ans += 1
print(ans)


import sys
stdin = sys.stdin
ip = lambda : int(sp())
fp = lambda : float(sp())
lp = lambda : list(map(int, stdin.readline().split()))
sp = lambda : stdin.readline().rstrip()
yp = lambda : print('Yes')
np = lambda : print('No')
from collections import Counter

class union_find:

	def __init__(self, n):
		self.n = n
		self.par = [-1 for i in range(n)]
		self.rank = [0] * n

	def find(self, x):
		if self.par[x] < 0:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.par[x] > self.par[y]:
			(x, y) = (y, x)
		self.par[x] += self.par[y]
		self.par[y] = x

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def size(self, x):
		return -self.par[self.find(x)]

	def members(self, x):
		root = self.find(x)
		return [i for i in range(self.n) if self.find(i) == root]

	def roots(self):
		return [i for (i, x) in enumerate(self.par) if x < 0]

	def all_group_member(self):
		return {r: self.members(r) for r in self.roots()}
(n, m) = lp()
a = lp()
uf = union_find(n)
for _ in range(m):
	(x, y) = lp()
	uf.union(x - 1, y - 1)
ans = 0
for i in range(n):
	now = a[i] - 1
	if uf.same(i, now):
		ans += 1
print(ans)


(n, m) = list(map(int, input().split()))
p = list(map(int, input().split()))
num = [[] for _ in range(n)]
for i in range(m):
	(x, y) = list(map(int, input().split()))
	num[x - 1].append(y)
	num[y - 1].append(x)
seen = [False] * n
ans = list(range(n))
for i in range(n):
	if seen[i] == False:
		queue = [i]
		seen[i] = True
		for j in range(n):
			if len(queue) == 0:
				break
			num1 = queue.pop()
			ans[num1] = i
			for k in range(len(num[num1])):
				num2 = num[num1][k] - 1
				if seen[num2] == False:
					queue.append(num2)
					seen[num2] = True
ans2 = 0
for i in range(n):
	if ans[i] == ans[p[i] - 1]:
		ans2 += 1
print(ans2)