class UnionFind:

    # 初期化

    def __init__(self, n_nodes):

        # 親要素のノード番号を格納する.

        # self.parent[x] == x の時，そのノードは根.

        self.parent = [i for i in range(n_nodes)]



        # 木の高さを格納する．

        self.rank = [0] * n_nodes



    # 検索. 根を返す.

    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[y] = x

        else:

            self.parent[x] = y

            if self.rank[x] == self.rank[y]:

                self.rank[y] += 1



    # 同じ集合に属するか判定

    def check(self, x, y):

        return self.find(x) == self.find(y)





N, M = list(map(int, input().split()))

p = list(map(int, input().split()))



tree = UnionFind(N)



for _ in range(M):

    x, y = list(map(int, input().split()))

    tree.unite(x - 1, y - 1)



ans = 0

for i in range(N):

    if tree.check(i, p[i] - 1):

        ans += 1



print(ans)

import sys



sys.setrecursionlimit(10 ** 6)

INF = float("inf")

MOD = 10 ** 9 + 7





def input():

    return sys.stdin.readline().strip()





class UnionFind:

    def __init__(self, n_nodes):

        self.n_nodes = n_nodes



        # self.parents[x] < 0 の時，xが根である．

        # また，xが根の時，(-1) * (同一グループの要素数) が格納されるようになる.

        self.parents = [-1] * n_nodes



    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



        # 常にxの方が要素数が多くなるように，スワップする

        if self.parents[x] > self.parents[y]:

            x, y = y, x



        # 要素数の少ない方のグループを，要素数が多い方の木に貼る．

        self.parents[x] += self.parents[y]

        self.parents[y] = x



    def get_size(self, x):

        return -self.parents[self.find(x)]



    def is_same(self, x, y):

        return self.find(x) == self.find(y)



    def get_members(self, x):

        parent = self.find(x)

        return [i for i in range(self.n_nodes) if self.find(i) == parent]



    def get_parent_list(self):

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



    def get_n_groups(self):

        return len(self.get_parent_list())



    def get_members_dict(self):

        return {par: self.get_members(par) for par in self.get_parent_list()}





def main():

    N, M = list(map(int, input().split()))

    P = list([int(x) - 1 for x in input().split()])

    tree = UnionFind(N)

    for _ in range(M):

        x, y = [int(x) - 1 for x in input().split()]

        tree.unite(x, y)



    ans = 0

    for i in range(N):

        if tree.is_same(i, P[i]):

            ans += 1



    print(ans)





if __name__ == "__main__":

    main()

class UnionFind:
    # 初期化
    def __init__(self, n_nodes):
        # 親要素のノード番号を格納する.
        # self.parent[x] == x の時，そのノードは根.
        self.parent = [i for i in range(n_nodes)]
        # 木の高さを格納する．
        self.rank = [0] * n_nodes

    # 検索. 根を返す.
    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[y] = x
        else:
            self.parent[x] = y
            if self.rank[x] == self.rank[y]:
                self.rank[y] += 1

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


N, M = list(map(int, input().split()))
p = list(map(int, input().split()))
tree = UnionFind(N)
for _ in range(M):
    x, y = list(map(int, input().split()))
    tree.unite(x - 1, y - 1)
ans = 0
for i in range(N):
    if tree.check(i, p[i] - 1):
        ans += 1
print(ans)

import sys

sys.setrecursionlimit(10**6)
INF = float("inf")
MOD = 10**9 + 7


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


class UnionFind:
    def __init__(self, n_nodes):
        self.n_nodes = n_nodes
        # self.parents[x] < 0 の時，xが根である．
        # また，xが根の時，(-1) * (同一グループの要素数) が格納されるようになる.
        self.parents = [-1] * n_nodes

    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
        # 常にxの方が要素数が多くなるように，スワップする
        if self.parents[x] > self.parents[y]:
            x, y = y, x
        # 要素数の少ない方のグループを，要素数が多い方の木に貼る．
        self.parents[x] += self.parents[y]
        self.parents[y] = x

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

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

    def get_members(self, x):
        parent = self.find(x)
        return [i for i in range(self.n_nodes) if self.find(i) == parent]

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

    def get_n_groups(self):
        return len(self.get_parent_list())

    def get_members_dict(self):
        return {par: self.get_members(par) for par in self.get_parent_list()}


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


if __name__ == "__main__":
    main()

+import sys + +sys.setrecursionlimit(10**6) +INF = float("inf") +MOD = 10**9 + 7 + + +def input(): +    return sys.stdin.readline().strip() + + -    # 初期化 -        # 親要素のノード番号を格納する. -        # self.parent[x] == x の時，そのノードは根. -        self.parent = [i for i in range(n_nodes)] -        # 木の高さを格納する． -        self.rank = [0] * n_nodes +        self.n_nodes = n_nodes +        # self.parents[x] < 0 の時，xが根である． +        # また，xが根の時，(-1) * (同一グループの要素数) が格納されるようになる. +        self.parents = [-1] * n_nodes -    # 検索. 根を返す. -        if self.parent[x] == x: +        if self.parents[x] < 0: -            # 一度調べた値は，根に繋ぎ直す. -            self.parent[x] = self.find(self.parent[x]) -            return self.parent[x] +            self.parents[x] = self.find(self.parents[x]) +            return self.parents[x] -    # 併合. -    # 木の高さが低くなるように. -    # 親要素の書き換えは少ない方がいい -        # 根を探す． -        # 根が同じ場合はそのまま -        # 木の高さを比較し，低い方を高い方の根に貼る. -        if self.rank[x] > self.rank[y]: -            self.parent[y] = x -        else: -            self.parent[x] = y -            if self.rank[x] == self.rank[y]: -                self.rank[y] += 1 +        # 常にxの方が要素数が多くなるように，スワップする +        if self.parents[x] > self.parents[y]: +            x, y = y, x +        # 要素数の少ない方のグループを，要素数が多い方の木に貼る． +        self.parents[x] += self.parents[y] +        self.parents[y] = x -    # 同じ集合に属するか判定 -    def check(self, x, y): +    def get_size(self, x): +        return -self.parents[self.find(x)] + +    def is_same(self, x, y): +    def get_members(self, x): +        parent = self.find(x) +        return [i for i in range(self.n_nodes) if self.find(i) == parent] -N, M = list(map(int, input().split())) -p = list(map(int, input().split())) -tree = UnionFind(N) -for _ in range(M): -    x, y = list(map(int, input().split())) -    tree.unite(x - 1, y - 1) -ans = 0 -for i in range(N): -    if tree.check(i, p[i] - 1): -        ans += 1 -print(ans) +    def get_parent_list(self): +        return [i for i, x in enumerate(self.parents) if x < 0] + +    def get_n_groups(self): +        return len(self.get_parent_list()) + +    def get_members_dict(self): +        return {par: self.get_members(par) for par in self.get_parent_list()} + + +def main(): +    N, M = list(map(int, input().split())) +    P = list([int(x) - 1 for x in input().split()]) +    tree = UnionFind(N) +    for _ in range(M): +        x, y = [int(x) - 1 for x in input().split()] +        tree.unite(x, y) +    ans = 0 +    for i in range(N): +        if tree.is_same(i, P[i]): +            ans += 1 +    print(ans) + + +if __name__ == "__main__": +    main()