import sys



sys.setrecursionlimit(10000)

INF = float('inf')





class WeightedUnionFind:

    def __init__(self, nodes):

        """

        :param collections.Iterable nodes:

        """

        self._parents = {k: k for k in nodes}

        self._ranks = {k: 0 for k in nodes}

        self._sizes = {k: 1 for k in nodes}

        # 直近の親からの重み。root なら 0

        self._weights = {k: 0 for k in nodes}



    def unite(self, x, y, w):

        """

        x が属する木と y が属する木を併合

        :param x:

        :param y:

        :param w: x と y の重みの差; (重み y) - (重み x)

        :return:

        """

        # それぞれの root をくっつけたいので root 間の重みに変換

        # x が上、y が下

        w += self.weight(x)

        w -= self.weight(y)



        x = self.find(x)

        y = self.find(y)

        if x == y:

            return



        # rank が小さい方が下

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

            # x が root

            self._parents[y] = x

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

            self._weights[x] = 0

            self._weights[y] = w

        else:

            # y が root

            self._parents[x] = y

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

            self._weights[x] = -w

            self._weights[y] = 0

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

                self._ranks[y] += 1



    def find(self, x):

        """

        x が属する木の root

        :param x:

        :return:

        """

        if self._parents[x] == x:

            return x

        root = self.find(self._parents[x])

        self._weights[x] += self._weights[self._parents[x]]

        self._parents[x] = root

        return root



    def size(self, x):

        """

        x が属する木のノード数

        :param x:

        :return:

        """

        return self._sizes[self.find(x)]



    def weight(self, x):

        """

        :param x:

        :return:

        """

        # 経路圧縮

        self.find(x)

        return self._weights[x]



    def diff(self, x, y):

        """

        (y の重み) - (x の重み)

        :param x:

        :param y:

        :return:

        """

        if self.find(x) == self.find(y):

            return self.weight(y) - self.weight(x)

        return float('inf')





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

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



uf = WeightedUnionFind(list(range(N + 1)))

for _ in range(M):

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

    uf.unite(x, y, 0)



ans = 0

for i in range(N):

    if uf.find(P[i]) == uf.find(i + 1):

        ans += 1



print(ans)

import os

import sys



if os.getenv("LOCAL"):

    sys.stdin = open("_in.txt", "r")



sys.setrecursionlimit(10 ** 9)

INF = float("inf")

IINF = 10 ** 18

MOD = 10 ** 9 + 7





# MOD = 998244353



class UnionFind:

    def __init__(self, size=None, nodes=None):

        """

        size か nodes どっちか指定。

        nodes は set、size は list を使う。

        :param int size:

        :param collections.Iterable nodes:

        """

        assert size is not None or nodes is not None

        if size is not None:

            self._parents = [i for i in range(size)]

            self._ranks = [0 for _ in range(size)]

            self._sizes = [1 for _ in range(size)]

        else:

            self._parents = {k: k for k in nodes}

            self._ranks = {k: 0 for k in nodes}

            self._sizes = {k: 1 for k in nodes}



    def unite(self, x, y):

        """

        x が属する木と y が属する木を併合

        :param x:

        :param y:

        """

        x = self.root(x)

        y = self.root(y)

        if x == y:

            return



        # rank が小さい方が下

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

            # x が root

            self._parents[y] = x

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

        else:

            # y が root

            self._parents[x] = y

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

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

                self._ranks[y] += 1



    def root(self, x):

        """

        x が属する木の root

        :param x:

        """

        if self._parents[x] == x:

            return x

        self._parents[x] = self.root(self._parents[x])

        return self._parents[x]



    def size(self, x):

        """

        x が属する木のノード数

        :param x:

        """

        return self._sizes[self.root(x)]





N, M = list(map(int, sys.stdin.buffer.readline().split()))

P = list(map(int, sys.stdin.buffer.readline().split()))

XY = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(M)]



uf = UnionFind(size=N + 1)

for x, y in XY:

    uf.unite(x, y)



ans = 0

for i, p in enumerate(P, start=1):

    ans += uf.root(i) == uf.root(p)

print(ans)

import sys

sys.setrecursionlimit(10000)
INF = float("inf")


class WeightedUnionFind:
    def __init__(self, nodes):
        """
        :param collections.Iterable nodes:
        """
        self._parents = {k: k for k in nodes}
        self._ranks = {k: 0 for k in nodes}
        self._sizes = {k: 1 for k in nodes}
        # 直近の親からの重み。root なら 0
        self._weights = {k: 0 for k in nodes}

    def unite(self, x, y, w):
        """
        x が属する木と y が属する木を併合
        :param x:
        :param y:
        :param w: x と y の重みの差; (重み y) - (重み x)
        :return:
        """
        # それぞれの root をくっつけたいので root 間の重みに変換
        # x が上、y が下
        w += self.weight(x)
        w -= self.weight(y)
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        # rank が小さい方が下
        if self._ranks[x] > self._ranks[y]:
            # x が root
            self._parents[y] = x
            self._sizes[x] += self._sizes[y]
            self._weights[x] = 0
            self._weights[y] = w
        else:
            # y が root
            self._parents[x] = y
            self._sizes[y] += self._sizes[x]
            self._weights[x] = -w
            self._weights[y] = 0
            if self._ranks[x] == self._ranks[y]:
                self._ranks[y] += 1

    def find(self, x):
        """
        x が属する木の root
        :param x:
        :return:
        """
        if self._parents[x] == x:
            return x
        root = self.find(self._parents[x])
        self._weights[x] += self._weights[self._parents[x]]
        self._parents[x] = root
        return root

    def size(self, x):
        """
        x が属する木のノード数
        :param x:
        :return:
        """
        return self._sizes[self.find(x)]

    def weight(self, x):
        """
        :param x:
        :return:
        """
        # 経路圧縮
        self.find(x)
        return self._weights[x]

    def diff(self, x, y):
        """
        (y の重み) - (x の重み)
        :param x:
        :param y:
        :return:
        """
        if self.find(x) == self.find(y):
            return self.weight(y) - self.weight(x)
        return float("inf")


N, M = list(map(int, input().split()))
P = list(map(int, input().split()))
uf = WeightedUnionFind(list(range(N + 1)))
for _ in range(M):
    x, y = list(map(int, input().split()))
    uf.unite(x, y, 0)
ans = 0
for i in range(N):
    if uf.find(P[i]) == uf.find(i + 1):
        ans += 1
print(ans)

import os
import sys

if os.getenv("LOCAL"):
    sys.stdin = open("_in.txt", "r")
sys.setrecursionlimit(10**9)
INF = float("inf")
IINF = 10**18
MOD = 10**9 + 7
# MOD = 998244353
class UnionFind:
    def __init__(self, size=None, nodes=None):
        """
        size か nodes どっちか指定。
        nodes は set、size は list を使う。
        :param int size:
        :param collections.Iterable nodes:
        """
        assert size is not None or nodes is not None
        if size is not None:
            self._parents = [i for i in range(size)]
            self._ranks = [0 for _ in range(size)]
            self._sizes = [1 for _ in range(size)]
        else:
            self._parents = {k: k for k in nodes}
            self._ranks = {k: 0 for k in nodes}
            self._sizes = {k: 1 for k in nodes}

    def unite(self, x, y):
        """
        x が属する木と y が属する木を併合
        :param x:
        :param y:
        """
        x = self.root(x)
        y = self.root(y)
        if x == y:
            return
        # rank が小さい方が下
        if self._ranks[x] > self._ranks[y]:
            # x が root
            self._parents[y] = x
            self._sizes[x] += self._sizes[y]
        else:
            # y が root
            self._parents[x] = y
            self._sizes[y] += self._sizes[x]
            if self._ranks[x] == self._ranks[y]:
                self._ranks[y] += 1

    def root(self, x):
        """
        x が属する木の root
        :param x:
        """
        if self._parents[x] == x:
            return x
        self._parents[x] = self.root(self._parents[x])
        return self._parents[x]

    def size(self, x):
        """
        x が属する木のノード数
        :param x:
        """
        return self._sizes[self.root(x)]


N, M = list(map(int, sys.stdin.buffer.readline().split()))
P = list(map(int, sys.stdin.buffer.readline().split()))
XY = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(M)]
uf = UnionFind(size=N + 1)
for x, y in XY:
    uf.unite(x, y)
ans = 0
for i, p in enumerate(P, start=1):
    ans += uf.root(i) == uf.root(p)
print(ans)

+import os -sys.setrecursionlimit(10000) +if os.getenv("LOCAL"): +    sys.stdin = open("_in.txt", "r") +sys.setrecursionlimit(10**9) - - -class WeightedUnionFind: -    def __init__(self, nodes): +IINF = 10**18 +MOD = 10**9 + 7 +# MOD = 998244353 +class UnionFind: +    def __init__(self, size=None, nodes=None): +        size か nodes どっちか指定。 +        nodes は set、size は list を使う。 +        :param int size: -        self._parents = {k: k for k in nodes} -        self._ranks = {k: 0 for k in nodes} -        self._sizes = {k: 1 for k in nodes} -        # 直近の親からの重み。root なら 0 -        self._weights = {k: 0 for k in nodes} +        assert size is not None or nodes is not None +        if size is not None: +            self._parents = [i for i in range(size)] +            self._ranks = [0 for _ in range(size)] +            self._sizes = [1 for _ in range(size)] +        else: +            self._parents = {k: k for k in nodes} +            self._ranks = {k: 0 for k in nodes} +            self._sizes = {k: 1 for k in nodes} -    def unite(self, x, y, w): +    def unite(self, x, y): -        :param w: x と y の重みの差; (重み y) - (重み x) -        :return: -        # それぞれの root をくっつけたいので root 間の重みに変換 -        # x が上、y が下 -        w += self.weight(x) -        w -= self.weight(y) -        x = self.find(x) -        y = self.find(y) +        x = self.root(x) +        y = self.root(y) -            self._weights[x] = 0 -            self._weights[y] = w -            self._weights[x] = -w -            self._weights[y] = 0 -    def find(self, x): +    def root(self, x): -        :return: -        root = self.find(self._parents[x]) -        self._weights[x] += self._weights[self._parents[x]] -        self._parents[x] = root -        return root +        self._parents[x] = self.root(self._parents[x]) +        return self._parents[x] -        :return: -        return self._sizes[self.find(x)] - -    def weight(self, x): -        """ -        :param x: -        :return: -        """ -        # 経路圧縮 -        self.find(x) -        return self._weights[x] - -    def diff(self, x, y): -        """ -        (y の重み) - (x の重み) -        :param x: -        :param y: -        :return: -        """ -        if self.find(x) == self.find(y): -            return self.weight(y) - self.weight(x) -        return float("inf") +        return self._sizes[self.root(x)] -N, M = list(map(int, input().split())) -P = list(map(int, input().split())) -uf = WeightedUnionFind(list(range(N + 1))) -for _ in range(M): -    x, y = list(map(int, input().split())) -    uf.unite(x, y, 0) +N, M = list(map(int, sys.stdin.buffer.readline().split())) +P = list(map(int, sys.stdin.buffer.readline().split())) +XY = [list(map(int, sys.stdin.buffer.readline().split())) for _ in range(M)] +uf = UnionFind(size=N + 1) +for x, y in XY: +    uf.unite(x, y) -for i in range(N): -    if uf.find(P[i]) == uf.find(i + 1): -        ans += 1 +for i, p in enumerate(P, start=1): +    ans += uf.root(i) == uf.root(p)