Buggy python submission (verdict: Time Limit Exceeded):
#coding:utf-8
n,m = map(int,input().split())
List = list(map(int,input().split()))


forest = [i for i in range(n+1)]
rank = [0 for i in range(n+1)]

def unite(x,y):
    while forest[x] != x:
        x = forest[x]
    a = rank[x]
    
    while forest[y] != y:
        y = forest[y]
    b = rank[y]
    
    if a <= b:
        if a == b:
            rank[x] += 1
        forest[y] = x
    else:
        forest[x] = y


def Find(x):
    if forest[x] != x:
        rank[x] = 1
        forest[x] = Find(forest[x])
        return forest[x]
    else:
        return x
    
    for xi in Q:
        forest[xi] = x
        rank[xi] = 1
    
    return x

    
cnt = 0
for i in range(m):
    x,y = map(int,input().split())
    unite(x,y)

for i in range(1,n+1):
    x = Find(i)
    y = Find(List[i-1])
    if x == y:
        cnt += 1
print(cnt)
    


Fixed submission:
#coding:utf-8

n,m = map(int,input().split())
List = list(map(int,input().split()))

class UnionFind3:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for i in range(size)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return 1
        return 0


cnt = 0
tree = UnionFind3(n)
for i in range(m):
    x,y = map(int,input().split())
    tree.union(x-1,y-1)

for i in range(n):
    a = tree.find(i)
    b = tree.find(List[i]-1)
    if a == b:
        cnt += 1

print(cnt)

Buggy python submission (verdict: Time Limit Exceeded):
#coding:utf-8
n,m = map(int,input().split())
List = list(map(int,input().split()))


forest = [i for i in range(n+1)]
rank = [0 for i in range(n+1)]

def unite(x,y):
    while forest[x] != x:
        x = forest[x]
    a = rank[x]
    
    while forest[y] != y:
        y = forest[y]
    b = rank[y]
    
    if a <= b:
        if a == b:
            rank[x] += 1
        forest[y] = x
    else:
        forest[x] = y


def Find(x):
    Q = []
    while forest[x] != x:
        x = forest[x]
        Q.append(x)
    """
    for xi in Q:
        forest[xi] = x
        rank[xi] = 1
    """
    return x

    
cnt = 0
for i in range(m):
    x,y = map(int,input().split())
    unite(x,y)

for i in range(1,n+1):
    x = Find(i)
    y = Find(List[i-1])
    if x == y:
        cnt += 1
print(cnt)
    


Fixed submission:
#coding:utf-8

n,m = map(int,input().split())
List = list(map(int,input().split()))

class UnionFind3:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for i in range(size)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return 1
        return 0


cnt = 0
tree = UnionFind3(n)
for i in range(m):
    x,y = map(int,input().split())
    tree.union(x-1,y-1)

for i in range(n):
    a = tree.find(i)
    b = tree.find(List[i]-1)
    if a == b:
        cnt += 1

print(cnt)

Buggy python submission (verdict: Time Limit Exceeded):
#coding:utf-8
n,m = map(int,input().split())
List = list(map(int,input().split()))


forest = [i for i in range(n+1)]
rank = [0 for i in range(n+1)]

def unite(x,y):
    while forest[x] != x:
        x = forest[x]
    a = rank[x]
    
    while forest[y] != y:
        y = forest[y]
    b = rank[y]
    
    if a <= b:
        if a == b:
            rank[x] += 1
        forest[y] = x
    else:
        forest[x] = y


def Find(x):
    Q = []
    while forest[x] != x:
        x = forest[x]
        Q.append(x)
    
    for xi in Q:
        forest[xi] = x
        rank[xi] = 1

    return x

    
cnt = 0
for i in range(m):
    x,y = map(int,input().split())
    unite(x,y)

for i in range(1,n+1):
    x = Find(i)
    y = Find(List[i-1])
    if x == y:
        cnt += 1
print(cnt)
    


Fixed submission:
#coding:utf-8

n,m = map(int,input().split())
List = list(map(int,input().split()))

class UnionFind3:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for i in range(size)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return 1
        return 0


cnt = 0
tree = UnionFind3(n)
for i in range(m):
    x,y = map(int,input().split())
    tree.union(x-1,y-1)

for i in range(n):
    a = tree.find(i)
    b = tree.find(List[i]-1)
    if a == b:
        cnt += 1

print(cnt)

Buggy python submission (verdict: Time Limit Exceeded):
#coding:utf-8
n,m = map(int,input().split())
List = list(map(int,input().split()))


forest = [i for i in range(n+1)]
rank = [0 for i in range(n+1)]

def unite(x,y):
    while forest[x] != x:
        x = forest[x]
    a = rank[x]
    
    while forest[y] != y:
        y = forest[y]
    b = rank[y]
    
    if a <= b:
        if a == b:
            rank[x] += 1
        forest[y] = x
    else:
        forest[x] = y


def Find(x,y):
    Q = []
    P = []
    while forest[x] != x:
        x = forest[x]
        Q.append(x)
            
    while forest[y] != y:
        y = forest[y]
        P.append(y)
    for xi in Q:
        forest[xi] = x
        rank[xi] = 1
    for yi in P:
        forest[yi] = y
        rank[yi] = 1
    if x == y:
        return 1
    else:
        return 0
    
cnt = 0
for i in range(m):
    x,y = map(int,input().split())
    unite(x,y)

for i in range(1,n+1):
    cnt += Find(i,List[i-1])
print(cnt)
    


Fixed submission:
#coding:utf-8

n,m = map(int,input().split())
List = list(map(int,input().split()))

class UnionFind3:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for i in range(size)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return 1
        return 0


cnt = 0
tree = UnionFind3(n)
for i in range(m):
    x,y = map(int,input().split())
    tree.union(x-1,y-1)

for i in range(n):
    a = tree.find(i)
    b = tree.find(List[i]-1)
    if a == b:
        cnt += 1

print(cnt)

Buggy python submission (verdict: Time Limit Exceeded):
#coding:utf-8
n,m = map(int,input().split())
List = list(map(int,input().split()))

class Tree:
    def __init__(self,par):
        self.par = par

forest = [Tree(i) for i in range(n+1)]
rank = [0 for i in range(n+1)]

def unite(x,y):
    while forest[x].par != x:
        x = forest[x].par
    a = rank[x]
    
    while forest[y].par != y:
        y = forest[y].par
    b = rank[y]
    
    if a <= b:
        if a == b:
            rank[x] += 1
        forest[y].par = x
    else:
        forest[x].par = y


def Find(x,y):
    Q = []
    P = []
    while forest[x].par != x:
        x = forest[x].par
        Q.append(x)
            
    while forest[y].par != y:
        y = forest[y].par
        P.append(y)
    for xi in Q:
        forest[xi].par = x
        rank[xi] = 1
    for yi in P:
        forest[yi].par = y
        rank[yi] = 1
    if x == y:
        return 1
    else:
        return 0
    
cnt = 0
for i in range(m):
    x,y = map(int,input().split())
    unite(x,y)

for i in range(1,n+1):
    cnt += Find(i,List[i-1])
print(cnt)
    


Fixed submission:
#coding:utf-8

n,m = map(int,input().split())
List = list(map(int,input().split()))

class UnionFind3:
    def __init__(self, size):
        # 負の値はルート (集合の代表) で集合の個数
        # 正の値は次の要素を表す
        self.table = [-1 for i in range(size)]

    # 集合の代表を求める
    def find(self, x):
        if self.table[x] < 0:
            return x
        else:
            # 経路の圧縮
            self.table[x] = self.find(self.table[x])
            return self.table[x]

    # 併合
    def union(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)
        if s1 != s2:
            if self.table[s1] <= self.table[s2]:
                # 小さいほうが個数が多い
                self.table[s1] += self.table[s2]
                self.table[s2] = s1
            else:
                self.table[s2] += self.table[s1]
                self.table[s1] = s2
            return 1
        return 0


cnt = 0
tree = UnionFind3(n)
for i in range(m):
    x,y = map(int,input().split())
    tree.union(x-1,y-1)

for i in range(n):
    a = tree.find(i)
    b = tree.find(List[i]-1)
    if a == b:
        cnt += 1

print(cnt)