CodeEff/ECCO huggingface dataset:
# Original solution


class UnionFind:

    def __init__(self, n):
        self.p = {i: i for i in range(n)}
        self.r = {i: 0 for i in range(n)}

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

    def merge(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        if self.r[x] == self.r[y]:
            self.r[x] += 1
        elif self.r[x] > self.r[y]:
            x, y = y, x
        self.p[x] = y

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

    def cluster(self):
        c = {}
        for x in self.p:
            xx = self.root(x)
            if xx not in c:
                c[xx] = {x}
            else:
                c[xx].add(x)
        return c


def main():
    n, m = list(map(int, input().split()))
    pp = list(map(int, input().split()))
    uf = UnionFind(n)
    for _ in range(m):
        x, y = list(map(int, input().split()))
        uf.merge(x - 1, y - 1)
    cc = uf.cluster()
    count = 0
    for clt in list(cc.values()):
        p = set(pp[i] - 1 for i in clt)
        count += len(p & clt)
    print(count)


if __name__ == '__main__':
    main()


# Optimized solution


class UnionFind:

    def __init__(self, n):
        self.p = {i: i for i in range(n)}
        self.r = {i: 0 for i in range(n)}

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

    def merge(self, x, y):
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        if self.r[x] < self.r[y]:
            self.p[x] = y
        else:
            self.p[y] = x
            if self.r[x] == self.r[y]:
                self.r[x] += 1

    def cluster(self):
        c = {}
        for x in self.p:
            xx = self.root(x)
            if xx not in c:
                c[xx] = {x}
            else:
                c[xx].add(x)
        return c


def main():
    n, m = list(map(int, input().split()))
    pp = list(map(int, input().split()))
    uf = UnionFind(n)
    for _ in range(m):
        x, y = list(map(int, input().split()))
        uf.merge(x - 1, y - 1)
    cc = uf.cluster()
    count = 0
    for clt in list(cc.values()):
        p = set(pp[i] - 1 for i in clt)
        count += len(p & clt)
    print(count)


if __name__ == '__main__':
    main()
# Original solution
def main():
    def find(x):
        if par[x] < 0:
            return x
        else:
            par[x] = find(par[x])
            return par[x]

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

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

    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    par = [-1] * n
    for _ in range(m):
        x, y = list(map(int, input().split()))
        x -= 1
        y -= 1
        unite(x, y)

    r = 0
    for i1 in range(n):
        ichi = p.index(i1 + 1)
        r += same(i1, ichi)
    print(r)


if __name__ == '__main__':
    main()


# Optimized solution
import sys
input = sys.stdin.readline
def main():
    def find(x):
        if par[x] < 0:
            return x
        else:
            par[x] = find(par[x])
            return par[x]

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

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

    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    pdic = {e :0 for e in range(n)}
    for i, pe in enumerate(p):
        pdic[pe] = i

    par = [-1] * n
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x-1, y-1)

    r = 0
    for i1 in range(n):
        r += same(i1, pdic[i1+1])
    print(r)


if __name__ == '__main__':
    main()
# Original solution
# ARC097D - Equals
import sys

input = sys.stdin.readline
sys.setrecursionlimit(10 ** 9)


def dfs(v: int, color: int) -> None:
    seen[v] = 1  # make vertex v searched
    group[v] = color
    for u in G[v]:  # search vertices available from v recursively
        if not seen[u]:  # skip if already searched
            dfs(u, color)


def main():
    # check i and Pi are connected components or not
    global G, seen, group
    N, M = tuple(map(int, input().split()))
    P = tuple(map(int, input().split()))
    E = tuple(tuple(map(int, input().split())) for _ in range(M))
    G = [[] for _ in range(N + 1)]  # construct a graph (1-idx)
    for v, u in E:
        G[v] += [u]
        G[u] += [v]
    seen, group = [0] * (N + 1), [0] * (N + 1)
    color = 1
    for i in range(1, N + 1):  # connected components have the same color
        if not seen[i]:
            dfs(i, color)
            color += 1
    ans = sum(group[i] == group[p] for i, p in enumerate(P, 1))
    print(ans)


if __name__ == "__main__":
    main()

# Optimized solution
# ARC097D - Equals
import sys

input = sys.stdin.readline
sys.setrecursionlimit(10 ** 9)


def dfs(v: int, color: int) -> None:
    group[v] = color  # make vertex v searched
    for u in G[v]:  # search vertices available from v recursively
        if not group[u]:  # skip if already searched
            dfs(u, color)


def main():
    # check i and Pi are connected components or not
    global G, group
    N, M = tuple(map(int, input().split()))
    P = tuple(map(int, input().split()))
    E = tuple(tuple(map(int, input().split())) for _ in range(M))
    G = [[] for _ in range(N + 1)]  # construct a graph (1-idx)
    for v, u in E:
        G[v] += [u]
        G[u] += [v]
    group = [0] * (N + 1)
    color = 1
    for v in range(1, N + 1):  # connected components have the same color
        if not group[v]:
            dfs(v, color)
            color += 1
    ans = sum(group[i] == group[p] for i, p in enumerate(P, 1))
    print(ans)


if __name__ == "__main__":
    main()
# Original solution
# ARC097D - Equals
import sys

input = sys.stdin.readline
sys.setrecursionlimit(10 ** 9)


def dfs(v: int, color: int) -> None:
    group[v] = color  # make vertex v searched
    for u in G[v]:  # search vertices available from v recursively
        if not group[u]:  # skip if already searched
            dfs(u, color)


def main():
    # check i and Pi are connected components or not
    global G, group
    N, M = tuple(map(int, input().split()))
    P = tuple(map(int, input().split()))
    E = tuple(tuple(map(int, input().split())) for _ in range(M))
    G = [[] for _ in range(N + 1)]  # construct a graph (1-idx)
    for v, u in E:
        G[v] += [u]
        G[u] += [v]
    group = [0] * (N + 1)
    color = 1
    for v in range(1, N + 1):  # connected components have the same color
        if not group[v]:
            dfs(v, color)
            color += 1
    ans = sum(group[i] == group[p] for i, p in enumerate(P, 1))
    print(ans)


if __name__ == "__main__":
    main()

# Optimized solution
# ARC097D - Equals (ABC097D)
import sys
input = sys.stdin.readline


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

    def find(self, x):  # find the group (root) of a vertex
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def is_same(self, x, y):  # check two vertices are in the same group
        return self.find(x) == self.find(y)

    def unite(self, x, y):  # unite two groups
        x, y = self.find(x), self.find(y)
        if x == y:  # the same group
            return
        # unite a small one to a bigger one to balance trees
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


def main():
    # check i and Pi are connected components or not
    N, M = tuple(map(int, input().split()))
    P = tuple(map(int, input().split()))
    E = tuple(tuple(map(int, input().split())) for _ in range(M))
    U = UnionFind(N)  # construct a Union-Find tree (1-idx)
    for v, u in E:  # connected components are in the same group
        U.unite(v, u)
    ans = sum(U.is_same(i, p) for i, p in enumerate(P, 1))
    print(ans)


if __name__ == "__main__":
    main()
# Original solution
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))
uf = {i:-1 for i in range(1,n+1)}

def get_p(i):
  while uf[i] != i:
    if uf[i] == -1:
      return i
    i = uf[i]
  return i

for _ in range(m):
  x,y = list(map(int,input().split()))
  if x > y:
    x,y = y,x
  if uf[x]== uf[y] == -1:
    uf[x] = x
    uf[y] = x
  elif uf[x] != -1 and uf[y] != -1:
    p = get_p(x)
    uf[x] = p
    index = y
    while index != uf[index]:
      index = uf[y]
      uf[y] = p
      y = index
    else:
      uf[index] = p
  else:
    if uf[x] == -1:
      p = get_p(y)
    else:
      p = get_p(x)
    uf[x] = p
    uf[y] = p

ans = 0  
for i, p in enumerate(P):
  if get_p(i+1) == get_p(p):
    ans += 1
print(ans)

# Optimized solution
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))

uf = {i:i for i in range(1,n+1)}

def get_parent(i):
  lst = []
  while uf[i] != i:
    lst.append(i)
    i = uf[i]
  for l in lst[:-1]:
    uf[l] = i
  return i

def unite(i,j):
  p = get_parent(i)
  uf[get_parent(j)] = p

def same(i,j):
  return get_parent(i) == get_parent(j)

for _ in range(m):
  x,y = list(map(int,input().split()))
  unite(x,y)

ans = 0
for i in range(1,n+1):
  ans += int(same(P[i-1],uf[i]))
print(ans)
# Original solution
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))

uf = {i:i for i in range(1,n+1)}

def get_parent(i):
  lst = []
  while uf[i] != i:
    lst.append(i)
    i = uf[i]
  for l in lst[:-1]:
    uf[l] = i
  return i

def unite(i,j):
  p = get_parent(i)
  uf[get_parent(j)] = p

def same(i,j):
  return get_parent(i) == get_parent(j)

for _ in range(m):
  x,y = list(map(int,input().split()))
  unite(x,y)

ans = 0
for i in range(1,n+1):
  ans += int(same(P[i-1],uf[i]))
print(ans)



# Optimized solution
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))

uf = {i:i for i in range(1,n+1)}

def get_parent(i):
  lst = []
  while uf[i] != i:
    lst.append(i)
    i = uf[i]
  for l in lst[:-1]:
    uf[l] = i
  return i

def unite(i,j):
  p = get_parent(i)
  uf[get_parent(j)] = p

def same(i,j):
  return get_parent(i) == get_parent(j)

for _ in range(m):
  x,y = list(map(int,input().split()))
  unite(x,y)

ans = 0
for i in range(1,n+1):
  ans += same(P[i-1],uf[i])
print(ans)
# Original solution
n,m=list(map(int,input().split()))
root=[i for i in range(n+1)]
rank=[0]*(n+1)
def find(x):
    if x==root[x]:
        return x 
    else:
        return find(root[x])

def union(x1,y1):
    x=find(x1)
    y=find(y1)
    if rank[x]>rank[y]:
        root[y]=x 
    elif rank[x]<=rank[y]:
        root[x]=y
        if rank[x]==rank[y]:
            rank[y]+=1
def k_sub():    
    p=list(map(int,input().split()))
    p=[-1]+p 
    for _ in range(m):
        x,y=list(map(int,input().split()))
        union(x,y)
    d=[[] for i in range(n+1)]
    u=[[] for i in range(n+1)]
    for i in range(1,n+1):
        d[find(i)].append(i)
        u[find(i)].append(p[i])
    cnt=0
    for i in range(1,n+1):
        for candidate in d[i]:
            cnt+=(candidate in u[i])
    print(cnt)
if __name__=='__main__':
    k_sub()

# Optimized solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
uf={i:i for i in range(1,n+1)}
def get_p(i):
    lst=[]
    while uf[i]!=i:
        lst.append(i)
        i=uf[i]
    for l in lst[:-1]:
        uf[l]=i 
    return i 

def unite(i,j):
    uf[get_p(i)]=get_p(j)
def same(i,j):
    return get_p(i)==get_p(j)

def main():
    for i in range(m):
        x,y=list(map(int,input().split()))
        unite(x,y)
    cnt=0
    for i in range(1,n+1):
        cnt+=same(p[i-1],uf[i])
    print(cnt)    
if __name__=='__main__':
    main()
# Original solution
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
 
    def root(self, i):
        while self.parent[i] != i:
            i = self.parent[i]
        return i
    def find(self, x, y):
        return self.root(x) == self.root(y)
 
    def union(self, i, j):
        i = self.root(i)
        j = self.root(j)
        self.parent[j] = i
N, M = list(map(int, input().split()))
ps = list(map(int, input().split()))
ps = [i-1 for i in ps]
swap =[list(map(int, input().split())) for i in range(M)]
u = UnionFind(N)
for x, y in swap:
    u.union(x-1, y-1)
ans = 0
for i, p in enumerate(ps):
    if u.find(i, p):
        ans += 1
print(ans)

# Optimized solution
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
 
    def root(self, i):
        if self.parent[i] == i:
            return i
        else:
            self.parent[i] = self.root(self.parent[i])
            return self.parent[i]
    
    def find(self, x, y):
        return self.root(x) == self.root(y)
 
    def union(self, i, j):
        i = self.root(i)
        j = self.root(j)
        self.parent[j] = i
N, M = list(map(int, input().split()))
ps = list(map(int, input().split()))
ps = [i-1 for i in ps]
swap =[list(map(int, input().split())) for i in range(M)]
u = UnionFind(N)
for x, y in swap:
    u.union(x-1, y-1)
ans = 0
for i, p in enumerate(ps):
    if u.find(i, p):
        ans += 1
print(ans)
# Original solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
r=[i for i in range(n)]
sp=[{p[i]-1} for i in range(n)]
def union(x,y):
  rx=root(x)
  ry=root(y)
  if rx==ry:
    return
  else:
    r[rx]=ry
    sp[ry]=sp[rx]|sp[ry]
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def get(x):
  return sp[root(x)]
for i in range(m):
  a,b=list(map(int,input().split()))
  union(a-1,b-1)
ans=0
for i in range(n):
  if (i in get(i)) or i+1==p[i]:
    ans+=1
print(ans)

# Optimized solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
r=[i for i in range(n)]
sp=[{p[i]-1} for i in range(n)]
def union(x,y):
  rx=root(x)
  ry=root(y)
  if rx==ry:
    return
  else:
    r[rx]=ry
    sp[ry]=sp[rx]|sp[ry]
    sp[rx]={}
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def get(x):
  return sp[root(x)]
for i in range(m):
  a,b=list(map(int,input().split()))
  union(a-1,b-1)
ans=0
for i in range(n):
  if (i in get(i)) or i+1==p[i]:
    ans+=1
print(ans)
# Original solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
r=[i for i in range(n)]
sp=[{p[i]-1} for i in range(n)]
def union(x,y):
  rx=root(x)
  ry=root(y)
  if rx==ry:
    return
  else:
    r[rx]=ry
    sp[ry]=sp[rx]|sp[ry]
    sp[rx]={}
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def get(x):
  return sp[root(x)]
for i in range(m):
  a,b=list(map(int,input().split()))
  union(a-1,b-1)
ans=0
for i in range(n):
  if (i in get(i)) or i+1==p[i]:
    ans+=1
print(ans)

# Optimized solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
r=[i for i in range(n)]
def union(x,y):
  rx=root(x)
  ry=root(y)
  if rx==ry:
    return
  else:
    r[rx]=ry
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
for i in range(m):
  a,b=list(map(int,input().split()))
  union(a-1,b-1)
ans=0
for i in range(n):
  if root(i)==root(p[i]-1) or i+1==p[i]:
    ans+=1
print(ans)
# Original solution
n, m = list(map(int, input().split()))
pn = list([int(x)-1 for x in 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 = [int(x)-1 for x in 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)

# Optimized solution
n, m = list(map(int, input().split()))
pn = list([int(x)-1 for x in 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 = [int(x)-1 for x in 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)
# Original solution
class UnionFind:
    def __init__(self, n, p):
        '木の初期化をする'
        # zero-index
        self.p  = [-1] * n
        self.rank = [1]*n
        # one -index
        self.g  = [set([i]) for i in range(n+1)]
        self.gp = [set([i]) for i in p]

    def find(self, x):
        'x の親を返す'
        if self.p[x] == -1:
            return x
        else:
            self.p[x] = self.find(self.p[x])
            return self.p[x]

    def unite(self, x, y):
        'rankの低い親を高い方のの親にする'
        if not self.same(x,y):
            x = self.find(x)
            y = self.find(y)
            if self.rank[x] > self.rank[y]:
                x,y = y,x
            elif self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.g[y+1] = self.g[y+1] | self.g[x+1]
            self.gp[y+1]= self.gp[y+1]| self.gp[x+1]
            self.p[x] = y # x の親を y にする
            return True
        else:
            return False

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


n,m = list(map(int,input().split()))
p = [0] + list(map(int,input().split()))

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

parent = set()
for i in range(n):
    parent.add(uf.find(i))
ans = 0
for i in parent:
    ans += len(uf.g[i+1]) + len(uf.gp[i+1]) - len(uf.g[i+1] | uf.gp[i+1])
print(ans)


# Optimized solution
class UnionFind:
    def __init__(self, n):
        '木の初期化をする'
        # zero-index
        self.p  = [-1] * n
        self.rank = [1]*n
        # one -index
        # self.g  = [set([i]) for i in range(n+1)]
        # self.gp = [set([i]) for i in p]

    def find(self, x):
        'x の親を返す'
        if self.p[x] == -1:
            return x
        else:
            self.p[x] = self.find(self.p[x])
            return self.p[x]

    def unite(self, x, y):
        'rankの低い親を高い方のの親にする'
        if not self.same(x,y):
            x = self.find(x)
            y = self.find(y)
            if self.rank[x] > self.rank[y]:
                x,y = y,x
            elif self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            # self.g[y+1] = self.g[y+1] | self.g[x+1]
            # self.gp[y+1]= self.gp[y+1]| self.gp[x+1]
            self.p[x] = y # x の親を y にする
            return True
        else:
            return False

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


n,m = list(map(int,input().split()))
p = [set([int(i)]) for i in input().split()]
r = [set([int(i)]) for i in range(1,n+1)]
uf = UnionFind(n)
for i in range(m):
    x,y = list(map(int,input().split()))
    uf.unite(x-1,y-1)
parent = set()
for i in range(n):
    parent.add(uf.find(i))
    p[uf.find(i)] = p[uf.find(i)] | p[i]
    r[uf.find(i)] = r[uf.find(i)] | r[i]

ans = 0
for i in parent:
    ans += len(p[i]) + len(r[i]) - len(p[i] | r[i])
print(ans)
# Original solution
class UnionFind:
    def __init__(self, n, p):
        '木の初期化をする'
        # zero-index
        self.p  = [-1] * n
        self.rank = [1]*n
        # one -index
        self.g  = [set([i]) for i in range(n+1)]
        self.gp = [set([i]) for i in p]

    def find(self, x):
        'x の親を返す'
        if self.p[x] == -1:
            return x
        else:
            self.p[x] = self.find(self.p[x])
            return self.p[x]

    def unite(self, x, y):
        'rankの低い親を高い方のの親にする'
        if not self.same(x,y):
            x = self.find(x)
            y = self.find(y)
            if self.rank[x] > self.rank[y]:
                x,y = y,x
            elif self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.g[y+1] = self.g[y+1] | self.g[x+1]
            self.gp[y+1]= self.gp[y+1]| self.gp[x+1]
            self.p[x] = y # x の親を y にする
            return True
        else:
            return False

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

def main():
    n,m = list(map(int,input().split()))
    p = [0] + list(map(int,input().split()))

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

    parent = [False]*n
    ans = 0
    for i in range(n):
        j = uf.find(i)
        if not parent[j]:
            parent[j] = True
            ans += len(uf.g[j+1]) + len(uf.gp[j+1]) - len(uf.g[j+1] | uf.gp[j+1])
    # ans = 0
    # for j in parent:
    #     ans += len(uf.g[j+1]) + len(uf.gp[j+1]) - len(uf.g[j+1] | uf.gp[j+1])
    print(ans)
main()


# Optimized solution
class UnionFind:
    def __init__(self, n, p):
        '木の初期化をする'
        # zero-index
        self.p  = [-1] * n
        self.rank = [1]*n

    def find(self, x):
        'x の親を返す'
        if self.p[x] == -1:
            return x
        else:
            self.p[x] = self.find(self.p[x])
            return self.p[x]

    def unite(self, x, y):
        'rankの低い親を高い方のの親にする'
        if not self.same(x,y):
            x = self.find(x)
            y = self.find(y)
            if self.rank[x] > self.rank[y]:
                x,y = y,x
            elif self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.p[x] = y # x の親を y にする
            return True
        else:
            return False

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

def main():
    n,m = list(map(int,input().split()))
    p = list(map(int,input().split()))

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

    ans = 0
    for i,j in enumerate(p):
        ans += uf.same(i, j-1)
    print(ans)
main()