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: competition

Starter code:

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)

#ARC097D Equals
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)
    #print(f(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)
    
# for i in range(1, N+1):
#     find(i)

# print(p)    #
# print(par)  #

ans = 0
for i in range(1, N+1):
    if find(p[i]) == find(p[p[i]]):
        ans += 1
#         print(ans)  #
        
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
#print(ls)

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): # i番目の数字がいる場所の親とiの場所
    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)
#-memoが同じ数字だったら入れ替え可能-#
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):
    '''
    xの根を求める
    '''
    if par[x] < 0:
        return x
    else:
        par[x] = find(par[x])
        return par[x]


def union(x, y):
    '''
    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):
    '''
    xが属する集合の個数
    '''
    return -par[find(x)]


def same(x, y):
    '''
    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)

#Union Find
class union_find:
    #初期化
    #根なら-size,子なら親の頂点
    # par = [-1]*N
    def __init__(self, N):
        self.par = [-1]*N

    #xの根を求める
    def find(self, x):
        if self.par[x] < 0:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    #xとyの属する集合の併合
    def unite(self, x,y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return False
        else:
            #sizeの大きいほうがx
            if self.par[x] > self.par[y]:
                x,y = y,x
            self.par[x] += self.par[y]
            self.par[y] = x
            return True

    #xとyが同じ集合に属するかの判定
    def same(self, x,y):
        return self.find(x) == self.find(y)

    #xが属する集合の個数
    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):#par:
    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():
    #slove()
    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         #class内変数nに、外部から入力した値numを代入
        self.parents = [-1 for i in range(self.n)]
          #parentsは要素の親(1こ上のやつ)番号0~n-1を格納、自分が最親なら-(要素数)を格納(初期値は-1)

    #xの最親は誰？
    def find(self,x):
        if self.parents[x]<0:
            return x
        else:
            self.parents[x]=self.find(self.parents[x]) #再帰して1番上までいってる
                #調べながらparentsの値を更新してる！（経路圧縮）
            return self.parents[x]

    #結合せよ
    #xの親とyの親をくっつける
    def union(self,x,y):
        xx=self.find(x)  #xxはxの最親
        yy=self.find(y)  #yyはyの最親
        if xx==yy:
            return     #同じ屋根の下にあった場合は何もしない
        else:
            size_xx=abs(self.parents[xx]) #xが含まれる木のサイズ
            size_yy=abs(self.parents[yy]) #yが含まれる木のサイズ
            if size_xx>size_yy:
                xx,yy=yy,xx  #yyの方が大きい木、ってことにする

            self.parents[yy]+=self.parents[xx] #大きい木のサイズ更新
            self.parents[xx]=yy   #サイズが小さい木を大きい木に接ぐ

    #xの属する木の大きさ（まあunionでも使ったけど）
    def size(self,x):
        xx=self.find(x)
        return abs(self.parents[xx])

    #xとyはこの空の続く場所にいますか　いつものように笑顔でいてくれますか　今はただそれを願い続ける
    def same(self,x,y):
        return 1 if self.find(x)==self.find(y) else 0

    #xと　同じ木にいる　メンバーは？
    def members(self,x):
        xx=self.find(x)
        return [i for i in range(self.n) if self.find(i)==xx]
             #ifの条件式に漏れたら無視

    #最親だけを並べあげる
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0]
        #いやこれは天才すぎる、basisのenumerate.py参照

    #すべての最親について、メンバーを辞書で
    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): #root(x): 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): #merge(x,y): 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 #xの要素数が大きいように
        self.size[x] += self.size[y] #xの要素数を更新
        self.parent[y] = x #yをxにつなぐ
        return True
 
    def issame(self, x, y): #same(x,y): xとyが同じ組ならTrue
        return self.root(x) == self.root(y)
        
    def getsize(self,x): #size(x): xのいるグループの要素数を返す
        return self.size[self.root(x)]

# coding: utf-8
# Your code here!
import sys
readline = sys.stdin.readline
read = sys.stdin.read

#n = int(readline())
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)

#print(q,r)
ans = 0
for i in range(n):
    ans += len(q[i]&r[i])
    #print(q[i]&r[i])

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)

    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())
        
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)
ans = 0
for i in range(N):
    if uf.same(i,P[i]-1):
        ans += 1
print(ans)

import sys
import math
import collections
import bisect
import copy
import itertools

# import numpy as np

sys.setrecursionlimit(10 ** 7)
INF = 10 ** 16
MOD = 10 ** 9 + 7
# MOD = 998244353

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()])


# ===CODE===

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():  # 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):
    # Connected compoponent
    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
        else:
            if 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
        else:
            if 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
# sys.setrecursionlimit(100000)


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:
    """ 0-indexed Union Find Tree (a.k.a Disjoint Union Tree)
    """

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

    # retrun the root of element x
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    # unite the group include element x and group include element y
    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

    # get size of the gourp which element x belongs
    def get_size(self, x):
        return -self.parents[self.find(x)]

    # check if element x and element y is same group
    def same(self, x, y):
        return self.find(x) == self.find(y)

    # return groups as array of set
    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()  # 1-indexed
    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 LF(): return [float(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()

# Union-Find -- START --
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]
# Union-Find --- END ---

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

# main()
print((main()))


class UnionFind:
    def __init__(self, n):
        # n: 頂点数
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        # 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):
        # 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)
# uf上のgroupごとに、groupのindexとその要素の積集合のサイズをとる
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(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
    else:
        if 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)
    # print(G)

    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)

    # 連結成分内はswapで自由な位置に移動可能
    c = []
    for i in range(N):
        if not visited[i]:
            tmp = []
            dfs(i, tmp)
            c.append(tmp)
    # print(c)

    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)


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):
    if find(i)==find(ls[i]):
       ans2+=1
print(ans2)

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("mohu",i)
        
        
    
    
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())
pn = list(map(lambda x:int(x)-1, input().split()))
ls = [-1] * n
for i in pn:
    ls[pn[i]] = i
#print(ls)

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 = i
    place2 = ls[i]

    if find(place1)==find(place2):
       ans2+=1
print(ans2)

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)

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         #class内変数nに、外部から入力した値numを代入
        self.parents = [-1 for i in range(self.n)]
          #parentsは要素の親(1こ上のやつ)番号0~n-1を格納、自分が最親なら-(要素数)を格納(初期値は-1)

    #xの最親は誰？
    def find(self,x):
        if self.parents[x]<0:
            return x
        else:
            self.parents[x]=self.find(self.parents[x]) #再帰して1番上までいってる
                #調べながらparentsの値を更新してる！（経路圧縮）
            return self.parents[x]

    #結合せよ
    #xの親とyの親をくっつける
    def union(self,x,y):
        xx=self.find(x)  #xxはxの最親
        yy=self.find(y)  #yyはyの最親
        if xx==yy:
            return     #同じ屋根の下にあった場合は何もしない
        else:
            size_xx=abs(self.parents[xx]) #xが含まれる木のサイズ
            size_yy=abs(self.parents[yy]) #yが含まれる木のサイズ
            if size_xx>size_yy:
                xx,yy=yy,xx  #yyの方が大きい木、ってことにする

            self.parents[yy]+=self.parents[xx] #大きい木のサイズ更新
            self.parents[xx]=yy   #サイズが小さい木を大きい木に接ぐ

    #xの属する木の大きさ（まあunionでも使ったけど）
    def size(self,x):
        xx=self.find(x)
        return abs(self.parents[xx])

    #xとyはこの空の続く場所にいますか　いつものように笑顔でいてくれますか　今はただそれを願い続ける
    def same(self,x,y):
        return 1 if self.find(x)==self.find(y) else 0

    #xと　同じ木にいる　メンバーは？
    def members(self,x):
        xx=self.find(x)
        return [i for i in range(self.n) if self.find(i)==xx]
             #ifの条件式に漏れたら無視

    #最親だけを並べあげる
    def roots(self):
        return [i for i,x in enumerate(self.parents) if x < 0]
        #いやこれは天才すぎる、basisのenumerate.py参照

    #すべての最親について、メンバーを辞書で
    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)

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の方がサイズが大きいようにする
            i, j = j, i
        self.nodes[i] += self.nodes[j] #大きい方に小さい方を統合しサイズを登録する。
        self.nodes[j] = i # 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():  # 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 groups(self):  # 全てのグループごとの要素
        members_dict = {i: set() for i, x in enumerate(self.parents) if x < 0}
        for i in range(self.N):
            members_dict[self.find(i)].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.groups().values()):
    ans += sum((p[num] - 1 in lst) for num in lst)
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)

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

    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())

uf=UnionFind(N)
for x,y in xy:
    uf.union(x-1,y-1)
ans=sum(uf.same(i,P[i]-1)for i in range(N))
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)

#!/usr/bin/env python3
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.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+1)
p_list = list(map(int, input().split()))

for i in range(M):
    x, y = list(map(int, input().split()))
    uf.union(x, y)

ans = 0
for i in range(N):
    if uf.find(p_list[i]) == uf.find(i+1):
        ans += 1
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:
    # この時点でそれぞれのノードは自分を親としている
    # 初期化時に問題が0の頂点を認めるかに注意すること
    def __init__(self, n):
        self.N = n
        self.parent = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]

    # xの根を返す関数
    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)


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())

n, m = map(int, input().split())
p = list(map(int, input().split()))
a = [list(map(int, input().split())) for i in range(m)]
uf = UnionFind(n)
for i in range(m):
  uf.union(a[i][0]-1, a[i][1]-1)
ans = 0
for i in range(n):
  if uf.same(p[i]-1, i):
    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():
	#a = int(input())
	n, m = tin()
	#s = input()
	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
	#pa(ll)
	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
		#input = sys.stdin.readline
			
	ret = main()
	if ret is not None:
		print(ret)
__starting_point()

import sys
import math
import collections
import bisect
import copy
import itertools

# import numpy as np

sys.setrecursionlimit(10 ** 7)
INF = 10 ** 16
MOD = 10 ** 9 + 7
# MOD = 998244353

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()])


# ===CODE===

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(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)

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 func(x):
    return x - 1

def main():
    N, M = map(int, input().split())
    P = list(map(func, map(int, input().split())))
    uni = UnionFind(N)
    for _ in range(M):
        x, y = map(int, input().split())
        x -= 1
        y -= 1
        uni.union(x,y)

    ans = 0
    for i, p in enumerate(P):
        if uni.same(i,p):
            ans += 1

    print(ans)


def __starting_point():
    main()
__starting_point()

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:]: # セットの最初は{0}になっているため
    result += sum(1 for m in group if p_list[m-1] in group)

print(result)



class Union_Find():
    def __init__(self,N):
        """0,1,...,n-1を要素として初期化する.

        n:要素数
        """
        self.n=N
        self.parents=[-1]*N
        self.rank=[0]*N

    def find(self, x):
        """要素xの属している族を調べる.

        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,yを同一視する.

        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):
        """要素xの属している要素の数.

        x:要素
        """
        return -self.parents[self.find(x)]

    def same(self, x, y):
        """要素x,yは同一視されているか?

        x,y:要素
        """
        return self.find(x) == self.find(y)

    def members(self, x):
        """要素xが属している族の要素.
        ※族の要素の個数が欲しいときはsizeを使うこと!!

        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)

N, M = map(int, input().split())
P = list(map(int, 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())

uf = UnionFind(N)
for _ in range(M):
    x, y = map(int, input().split())
    uf.union(x-1, y-1)

ans = 0
for i in range(N):
    if uf.same(i, P[i]-1):
        ans += 1

print(ans)

# unionfind
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
			#木の高さが同じなら片方を1増やす
			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)

#「値iを含む位置jと位置iが同じグループに属している」という条件を満たすiの数を数える
ans=0
for i in range(N):
	if uf.root(P[i]) == uf.root(i):
		ans+=1
print(ans)

'''
自宅用PCでの解答
'''
import math
#import numpy as np
import itertools
import queue
import bisect
from collections import deque,defaultdict
import heapq as hpq
from sys import stdin,setrecursionlimit
#from scipy.sparse.csgraph import dijkstra
#from scipy.sparse import csr_matrix
ipt = stdin.readline
setrecursionlimit(10**7)
mod = 10**9+7
dir = [(-1,0),(0,-1),(1,0),(0,1)]
alp = "abcdefghijklmnopqrstuvwxyz"

#UnionFindのクラス
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
#print(ls)

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]])
#print(dic)
#print(par)
ans = 0
for i in range(n):
    if i in dic[find(i)]:
       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)

q=[-1]*N
for i in range(N):
    q[p[i]-1]=i
ans=0
for i in range(N):
    if same(i,q[i]):
        ans+=1
print(ans)

class Unionfind():  # 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 groups(self):  # 全てのグループごとの要素
        members_dict = {}
        for i in range(self.N):
            if self.find(i) not in members_dict:
                members_dict[self.find(i)] = set()
            members_dict[self.find(i)].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.groups().values()):
    ans += sum((p[num] - 1 in lst) for num in lst)
print(ans)


n,m=list(map(int, input().split()))
p=list([int(x)-1 for x in 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 is_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 members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    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())

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 in range(len(p)):
    if uf.is_same(i, p[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
        ##親要素のノード番号を格納。par[x]==xのときそのノードは根
        ##親とはその上にノードなし！！　
        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)