CodeEff/ECCO huggingface dataset:
# Original solution
N,M = list(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 = list(map(int, input().split()))
  uf.union(x-1,y-1)
  
ans = 0
for lis in list(uf.all_group_members().values()):
  s = set(lis)
  for a in s:
    if P[a]-1 in s:
      ans += 1
      
print(ans)

# Optimized solution
N,M = list(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+1)
for _ in range(M):
  x,y = list(map(int, input().split()))
  uf.union(x,y)
  
ans = 0
for i in range(N):
  if uf.same(i+1, P[i]):
    ans += 1
      
print(ans)
# Original solution
from collections import defaultdict
class UnionFind:
  
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0]*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 unite(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    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(self, x, y):
    return self.find(x)==self.find(y)
  
N, M = list(map(int, input().split()))
h = [int(i)-1 for i in input().split()]
dic1 = defaultdict(list)
dic2 = defaultdict(list)
u = UnionFind(N)
for i in range(M):
  a, b = list(map(int, input().split()))
  u.unite(a-1,b-1)

for c in range(N):
  p = u.find(c)
  dic1[p] += [c]
  dic2[p] += [h[c]]
ans = 0
for p in list(dic1.keys()):
  dic1[p].sort()
  dic2[p].sort()
  i = 0
  j = 0
  while i<len(dic1[p]) and j<len(dic2[p]):
    if dic1[p][i]==dic2[p][j]:
      i += 1
      j += 1
      ans += 1
    elif dic1[p][i]<dic2[p][j]:
      i += 1
    else:
      j += 1
    
print(ans)

# Optimized solution
class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0]*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 unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
    else:
      self.par[y] = x
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  

N, M, *L = list(map(int, open(0).read().split()))
p = L[:N]
ls = L[N:]
u = UnionFind(N+1)
for x,y in zip(*[iter(ls)]*2):
  u.unit(x,y)
inf = {p[i]:i for i in range(N)}
ans = sum(1 if u.same(i,inf[i]+1) else 0 for i in range(1,N+1))
print(ans)
# Original solution
class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0]*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 unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
    else:
      self.par[y] = x
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  

N, M, *L = list(map(int, open(0).read().split()))
p = L[:N]
ls = L[N:]
u = UnionFind(N+1)
for x,y in zip(*[iter(ls)]*2):
  u.unit(x,y)
inf = {p[i]:i for i in range(N)}
ans = sum(1 if u.same(i,inf[i]+1) else 0 for i in range(1,N+1))
print(ans)

# Optimized solution
class UnionFind:
  def __init__(self, n):
    self.par = [i for i in range(n)]
    self.rank = [0]*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 unit(self, x, y):
    x = self.find(x)
    y = self.find(y)
    if x==y:
      return
    elif self.rank[x]<self.rank[y]:
      self.par[x] = y
      return
    elif self.rank[y]<self.rank[x]:
      self.par[y] = x
    else:
      self.par[y] = x
      self.rank[x] += 1
      
  def same(self, x, y):
    return self.find(x)==self.find(y)
  

N, M, *L = list(map(int, open(0).read().split()))
p = L[:N]
ls = L[N:]
u = UnionFind(N+1)
for x,y in zip(*[iter(ls)]*2):
  u.unit(x,y)
inf = [0]*(N+1)
for i in range(N):
  inf[p[i]] = i
ans = sum(1 if u.same(i,inf[i]+1) else 0 for i in range(1,N+1))
print(ans)
# Original solution
n,m = list(map(int, input().split()))
P = [0]+list(map(int, input().split()))
XY = list(list(map(int, input().split())) for _ in range(m))
G = [[] for _ in range(n+1)]
for x, y in XY:
    G[x].append(y)
    G[y].append(x)

# print(n,m)
# print(P)
# print(XY)
# print(G)
# for i in range(len(G)):#########
#     print(i, G[i])###############

from collections import deque
q = deque()
vis = [False]*(n+1)
ans = 0
for i in range(1,len(G)):
    # print('i',i, 'G[i]',G[i])
    inc_x = set()
    inc_px = set()
    q.append(i)
    while q:
        # print(q)
        x = q.popleft()
        if vis[x]: continue
        vis[x] = True
        inc_x.add(x)
        inc_px.add(P[x])
        # print('x',x,'P[x]',P[x],'G[x]',G[x])
        for y in G[x]:
            # print('y',y)
            if vis[y]: continue
            q.append(y)
    # print('inc_x',inc_x)
    # print('inc_px',inc_px)
    # print('inc_x&inc_px',inc_x&inc_px)
    # print('len(inc_x&inc_px)',len(inc_x&inc_px))
    ans += len(inc_x & inc_px)

print(ans)


# Optimized solution
from collections import deque

n,m = list(map(int, input().split()))
P = [0]+list(map(int, input().split()))
XY = list(list(map(int, input().split())) for _ in range(m))
G = [[] for _ in range(n+1)]
for x, y in XY:
    G[x].append(y)
    G[y].append(x)

q = deque()
vis = [False]*(n+1)
ans = 0
for i in range(1,len(G)):
    set_x, set_px = set(), set()
    q.append(i)
    while q:
        x = q.popleft()
        if vis[x]: continue
        vis[x] = True
        set_x.add(x)
        set_px.add(P[x])
        for y in G[x]:
            if vis[y]: continue
            q.append(y)
    ans += len(set_x & set_px)
print(ans)
# Original solution
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 [0]*M]
z=[[i,1] for i in range(N)]

def root_find(a):
    while(a!=z[a][0]):
        a=z[a][0]
    return a

def union(a,b):
    ra=root_find(a[0])
    rb=root_find(b[0])
    if z[ra][1]<=z[rb][1]:
        z[ra][0]=rb
        z[rb][1]=max(z[rb][1],z[ra][1]+1)
    else:
        z[rb][0]=ra
        z[ra][1]=max(z[ra][1],z[rb][1]+1)
    
for i in range(M):
    union(z[xy[i][0]],z[xy[i][1]])

for i in range(N):
    z[i][0]=root_find(z[i][0])

dic=dict()

for i in range(N):
    zz=z[i][0]
    if zz not in list(dic.keys()):
        dic[zz]=[i]
    else:
        dic[zz].append(i)

list1=list(dic.values())
list2=[[] for _ in [0]*len(list1)]

for i in range(len(list1)):
    for a in list1[i]:
        list2[i].append(p[a])

cnt=0
for i in range(len(list1)):
    for a in list1[i]:
        if a in list2[i]:
            cnt+=1
print(cnt)

# Optimized solution
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 [0]*M]
z=[[i,1] for i in range(N)]

def root_find(a):
    while(a!=z[a][0]):
        a=z[a][0]
    return a

def union(a,b):
    ra=root_find(a[0])
    rb=root_find(b[0])
    if z[ra][1]<=z[rb][1]:
        z[ra][0]=rb
        z[rb][1]=max(z[rb][1],z[ra][1]+1)
    else:
        z[rb][0]=ra
        z[ra][1]=max(z[ra][1],z[rb][1]+1)
    
for i in range(M):
    union(z[xy[i][0]],z[xy[i][1]])

for i in range(N):
    z[i][0]=root_find(z[i][0])

dic=dict()

for i in range(N):
    zz=z[i][0]
    if zz not in list(dic.keys()):
        dic[zz]=[i]
    else:
        dic[zz].append(i)

list1=list(dic.values())
list2=[[p[a] for a in list1[i]] for i in range(len(list1))]

cnt=sum(len(set(list1[i])&set(list2[i])) for i in range(len(list1)))
print(cnt)
# Original solution
from collections import defaultdict

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

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        self.par[x] = y

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

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

uf = UnionFind(n)
for _ in range(m):
    x, y = list(map(int, input().split()))
    uf.unite(x-1, y-1)

a = defaultdict(list)
b = defaultdict(list)
for i in range(n):
    k = uf.find(i)
    a[k].append(i)
    b[k].append(p[i])

ans = 0
for k in list(a.keys()):
    ans += len(set(a[k]) & set(b[k]))

print(ans)


# Optimized solution
from collections import defaultdict

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

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

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        self.par[x] = y

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


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

uf = UnionFind(n)
for _ in range(m):
    x, y = list(map(int, input().split()))
    uf.unite(x-1, y-1)

ans = 0
for i in range(n):
    if uf.same(i, p[i]):
        ans += 1

print(ans)
# Original solution
import sys
input = sys.stdin.buffer.readline
N,M = list(map(int,input().split()))
p = [i-1 for i in map(int,input().split())]
alr = [False for i in range(N)]
xy = [[] for i in range(N)]
for i in range(M):
    x,y = list(map(int,input().split()))
    x -= 1
    y -= 1
    xy[x].append(y)
    xy[y].append(x)
count = 0

for i in range(N):
    if (not alr[i]) and (xy[i]):
        alr[i] = True
        stack = [i]
        indlist = set()
        indlist.add(p.index(i))
        numlist = set()
        numlist.add(i)
        while stack:
            j = stack.pop()
            for k in xy[j]:
                if not alr[k]:
                    alr[k] = True
                    stack.append(k)
                    numlist.add(k)
                    indlist.add(p.index(k))
        count += len(numlist & indlist)
    else:
        if (not alr[i]) and p[i] == i:
            count += 1
print(count)
                
    
        

# Optimized solution
import sys
input = sys.stdin.buffer.readline
N,M = list(map(int,input().split()))
p = [i-1 for i in map(int,input().split())]
alr = [False for i in range(N)]
xy = [[] for i in range(N)]
for i in range(M):
    x,y = list(map(int,input().split()))
    x -= 1
    y -= 1
    xy[x].append(y)
    xy[y].append(x)
count = 0

for i in range(N):
    if (not alr[i]) and (xy[i]):
        alr[i] = True
        stack = [i]
        numlist = set()
        numlist.add(i)
        while stack:
            j = stack.pop()
            for k in xy[j]:
                if not alr[k]:
                    alr[k] = True
                    stack.append(k)
                    numlist.add(k)
        indlist = set([p[i] for i in numlist])
        count += len(numlist & indlist)
    else:
        if (not alr[i]) and p[i] == i:
            count += 1
print(count)
# Original solution
N,M = list(map(int,input().split()))
p = [0] + [int(x) for x in input().split()]

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)

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

unionUF, unionp, par = [], [], []
for i in range(1, N+1):
    temp = UF.find(i)
    if temp in par:
        unionUF[par.index(temp)].add(i)
        unionp[par.index(temp)].add(p[i])
    else:
        par.append(temp)
        unionUF.append(set([i]))
        unionp.append(set([p[i]]))

ans = 0
for i in range(len(unionUF)):
    ans += len(unionUF[i] & unionp[i])
print(ans)

# Optimized solution
N,M = list(map(int,input().split()))
p = [0] + [int(x) for x in input().split()]

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)

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

unionUF, unionp = [set() for _ in range(N+1)], [set() for _ in range(N+1)]
for i in range(1, N+1):
    temp = UF.find(i)
    unionUF[temp].add(i)
    unionp[temp].add(p[i])

ans = 0
for i in range(len(unionUF)):
    ans += len(unionUF[i] & unionp[i])
print(ans)
# Original solution
#!/mnt/c/Users/moiki/bash/env/bin/python
N,M = list(map(int, input().split()))
p = list(map(int, input().split()))
swappair= [list(map(int, input().split())) for _ in range(M)]

union_list = [-1 for _ in range(N+1)]

def find(a): # get root
    while not union_list[a] == -1:
        a = union_list[a]
    return a

def merge(a,b): 
    ia = find(a)
    ib = find(b)
    if ia < ib:
        union_list[ib] = ia
    elif ia > ib:
        union_list[ia] = ib
    elif ia==ib:
        union_list[ia] -= 1
        union_list[ib] = ia
    


def is_same_grp(a,b):
    ia = find(a)
    ib = find(b)
    return ia == ib

for i in range(M):
    merge(*swappair[i])

ans = 0
for i in range(1,N+1):
    ans += int( is_same_grp(i, p[i-1]))

print(ans)




# Optimized solution
#!/mnt/c/Users/moiki/bash/env/bin/python
N,M = list(map(int, input().split()))
p = list(map(int, input().split()))
swappair= [list(map(int, input().split())) for _ in range(M)]

union_list = [-1 for _ in range(N+1)]

def find(a): # get root
    while not union_list[a] == -1:
        a = union_list[a]
    return a

def merge(a,b): 
    ia = find(a)
    ib = find(b)
    if ia == ib:
        return 
        
    if ia < ib:
        union_list[ib] = ia
    elif ia > ib:
        union_list[ia] = ib
    


def is_same_grp(a,b):
    ia = find(a)
    ib = find(b)
    return ia == ib

for i in range(M):
    merge(*swappair[i])

ans = 0
for i in range(1,N+1):
    ans += int( is_same_grp(i, p[i-1]))

print(ans)
# Original solution
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()))
p = [int(i)-1 for i in input().split() ]

uf = UnionFind(n)
for i in range(m):
    x,y = list(map(int,input().split()))
    uf.union(x-1,y-1)

ans=0
groups = list(uf.all_group_members().values())

for c in groups:
    ans+= len( set(c) & set(p[i] for i in c ) ) 
print(ans)
      


# Optimized solution
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()))
p = [int(i)-1 for i in input().split() ]

uf = UnionFind(n)
for i in range(m):
    x,y = list(map(int,input().split()))
    uf.union(x-1,y-1)

print((sum(uf.same(i,p[i]) for i in range(n) ) ))
# Original solution
class DisjointSet:
    def __init__(self,size):
        self.rank=[0]*size
        self.p=[0]*size
        for i in range(size):
            self.makeSet(i)
    
    def makeSet(self,i):
        self.p[i]=i
        self.rank[i]=0
    
    def same(self,x,y):
        return self.findSet(x) == self.findSet(y)
    
    def unite(self, x,y):
        self.link(self.findSet(x), self.findSet(y))
    
    def link(self, x, y):
        if(self.rank[x] > self.rank[y]):
            self.p[y] = x
        else:
            self.p[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y]+=1
     
    def findSet(self, x):
        if(x!=self.p[x]):
            self.p[x]=self.findSet(self.p[x])
        return self.p[x]

    def print(self):
        print(self.p)
        
def readinput():
    n,m=list(map(int,input().split()))
    p=list(map(int,input().split()))
    p.insert(0,0)
    pairs=[]
    for _ in range(m):
        pair=list(map(int,input().split()))
        pairs.append(pair)
    return n,m,p,pairs

def main(n,m,p,pairs):
    uft=DisjointSet(n+1)
    for x,y in pairs:
        if uft.same(x, y):
            pass
        else:
            uft.unite(x, y)

    #uft.print()

    #print(p)
    count=0
    for i in range(1,n+1):
        for j in range(1,n+1):
            if i==p[j]:
                #print(i,j)
                break
        if uft.same(i,j):
            #p[i],p[j] = p[j], p[i]
            count+=1
    
    return count

if __name__=='__main__':
    n,m,p,pairs=readinput()
    ans=main(n,m,p,pairs)
    print(ans)


# Optimized solution
class DisjointSet:
    def __init__(self,size):
        self.rank=[0]*size
        self.p=[0]*size
        for i in range(size):
            self.makeSet(i)
    
    def makeSet(self,i):
        self.p[i]=i
        self.rank[i]=0
    
    def same(self,x,y):
        return self.findSet(x) == self.findSet(y)
    
    def unite(self, x,y):
        self.link(self.findSet(x), self.findSet(y))
    
    def link(self, x, y):
        if(self.rank[x] > self.rank[y]):
            self.p[y] = x
        else:
            self.p[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y]+=1
     
    def findSet(self, x):
        if(x!=self.p[x]):
            self.p[x]=self.findSet(self.p[x])
        return self.p[x]

    def print(self):
        print(self.p)
        
def readinput():
    n,m=list(map(int,input().split()))
    p=list(map(int,input().split()))
    p.insert(0,0)
    pairs=[]
    for _ in range(m):
        pair=list(map(int,input().split()))
        pairs.append(pair)
    return n,m,p,pairs

def main(n,m,p,pairs):
    uft=DisjointSet(n+1)
    for x,y in pairs:
        if uft.same(x, y):
            pass
        else:
            uft.unite(x, y)

    #uft.print()

    #print(p)
    count=0
    for i in range(1,n+1):
        if uft.same(i,p[i]):
            #p[i],p[j] = p[j], p[i]
            count+=1
    
    return count

if __name__=='__main__':
    n,m,p,pairs=readinput()
    ans=main(n,m,p,pairs)
    print(ans)
# Original solution
n, m = list(map(int, input().split()))
ps = [int(p)-1 for p in input().split()]
xys = [tuple(int(x)-1 for x in input().split()) for _ in range(m)]

nodes = list(range(n))
union = {node:node for node in nodes}

def root(node):
    if union[node] == node:
        return node
    union[node] = root(union[node])
    return union[node]

for x, y in xys:
    rx = root(x)
    ry = root(y)
    union[rx] = ry

print((sum(root(i) == root(p) for i, p in enumerate(ps))))

# Optimized solution
n, m = list(map(int, input().split()))
ps = [int(p)-1 for p in input().split()]
xys = [tuple(int(x)-1 for x in input().split()) for _ in range(m)]

union = {node:node for node in range(n)}

def root(node):
    if union[node] == node:
        return node
    union[node] = root(union[node])
    return union[node]

for x, y in xys:
    union[root(x)] = root(y)

print((sum(root(i) == root(p) for i, p in enumerate(ps))))