CodeEff/ECCO huggingface dataset:
# 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=list(map(int,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
for List in list(uf.all_group_members().values()):
    tree=set()
    for i in range(len(List)):
        tree.add(p[List[i]])
    for g in range(len(List)):
        if List[g]+1 in tree:
            tree.remove(List[g]+1)
            ans+=1
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=list(map(int,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
for i in range(n):
    if uf.same(i,p[i]-1):
        ans+=1
print(ans)
# Original solution
import sys
readline = sys.stdin.readline

def root(x):
    if uf[x] == x:
        return x
    else:
        uf[x] = root(uf[x])
        return uf[x]

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

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx == ry:
        return
    uf[rx] = ry

N, M = list(map(int,readline().split()))
p = list(map(int,readline().split()))
p.insert(0, -1)
uf = [i for i in range(N+1)]
for i in range(M):
    a, b = (list(map(int,readline().split())))
    unite(a, b)
for i in range(1, N+1):
    root(i)

ans = 0
N += 1
match = [[] for i in range(N)]
for i in range(1, N):
    match[uf[i]].append(i)
for i in range(1, N):
    matchlen = len(match[i])
    for j in range(matchlen):
        if p[match[i][j]] in match[i]:
            ans += 1
print((str(ans)))

# Optimized solution
import sys
readline = sys.stdin.readline

def root(x):
    if uf[x] == x:
        return x
    else:
        uf[x] = root(uf[x])
        return uf[x]

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

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx == ry:
        return
    uf[rx] = ry

N, M = list(map(int,readline().split()))
p = list(map(int,readline().split()))
p.insert(0, -1)
uf = [i for i in range(N+1)]
for i in range(M):
    a, b = (list(map(int,readline().split())))
    unite(a, b)
for i in range(1, N+1):
    root(i)

ans = 0
#N += 1
#match = [[] for i in range(N)]
#for i in range(1, N):
#    match[uf[i]].append(i)
#for i in range(1, N):
#    matchlen = len(match[i])
#    for j in range(matchlen):
#        if p[match[i][j]] in match[i]:
#            ans += 1

for i in range(1, N+1):
    if same(i, p[i]):
        ans += 1
print((str(ans)))
# Original solution
import sys
readline = sys.stdin.readline

def root(x):
    if uf[x] == x:
        return x
    else:
        uf[x] = root(uf[x])
        return uf[x]

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

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx == ry:
        return
    uf[rx] = ry

N, M = list(map(int,readline().split()))
p = list(map(int,readline().split()))
p.insert(0, -1)
uf = [i for i in range(N+1)]
for i in range(M):
    a, b = (list(map(int,readline().split())))
    unite(a, b)
for i in range(1, N+1):
    root(i)

ans = 0
#N += 1
#match = [[] for i in range(N)]
#for i in range(1, N):
#    match[uf[i]].append(i)
#for i in range(1, N):
#    matchlen = len(match[i])
#    for j in range(matchlen):
#        if p[match[i][j]] in match[i]:
#            ans += 1

for i in range(1, N+1):
    if same(i, p[i]):
        ans += 1
print((str(ans)))

# Optimized solution
import sys
readline = sys.stdin.readline

def root(x):
    if uf[x] == x:
        return x
    else:
        uf[x] = root(uf[x])
        return uf[x]

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

def unite(x, y):
    rx = root(x)
    ry = root(y)
    if rx == ry:
        return
    uf[rx] = ry

N, M = list(map(int,readline().split()))
p = list(map(int,readline().split()))
p.insert(0, -1)
uf = [i for i in range(N+1)]
for i in range(M):
    a, b = (list(map(int,readline().split())))
    unite(a, b)
for i in range(1, N+1):
    root(i)

ans = 0
#戒めコード
#N += 1
#match = [[] for i in range(N)]
#for i in range(1, N):
#    match[uf[i]].append(i)
#for i in range(1, N):
#    matchlen = len(match[i])
#    for j in range(matchlen):
#        if p[match[i][j]] in match[i]:
#            ans += 1

for i in range(1, N+1):
    if same(i, p[i]):
        ans += 1
print((str(ans)))

#root(i)=root(j)ならばiとjは行き来できる(iはjの居る場所に到達できる)
#知りたいのはiがp[i]のいる位置に来れるかどうか
#root(i)=root(p[i])なら,iはp[i]の位置に来れる,すなわちi番目にiを持ってくることができる
# Original solution
# D - Equals

from collections import deque

N, M = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = [list(map(int, input().split())) for _ in range(M)]

neighbor = [[] for _ in range(N)]
for idx in range(M):
    neighbor[xy[idx][0]-1].append(xy[idx][1]-1)
    neighbor[xy[idx][1]-1].append(xy[idx][0]-1)
    
can_swap = []
visited = [-1]*N

for start in range(N):
    if visited[start] == -1:
        tmp = [start] # startから到達可能なpointのリスト
        d = deque([start])
        while d:
            current_point = d.pop()
            visited[current_point] = 1
            for next_point in neighbor[current_point]:
                if visited[next_point] == -1:
                    d.append(next_point)
                    tmp.append(next_point)
        can_swap.append(tmp)                

ans = 0
for idx_group in can_swap:
    tmp_p = [p[idx]-1 for idx in idx_group]
    ans += len(set(tmp_p) & set(idx_group))

print(ans)

# Optimized solution
# D - Equals Union Find

N, M = list(map(int, input().split()))
p = list(map(int, input().split()))
xy = [list(map(int, input().split())) for _ in range(M)]

# 負ならそのノードが根かつ絶対値が木の要素数を示す、正なら値のノードが根であることを示す
root = [-1] * N 

# 木の高さを示す
rank = [1] * N

# インデックスxを与えると、xの根を返す関数
def find_root(x):
    if root[x] < 0:
        return x
    else:
        root[x] = find_root(root[x])
        return root[x]
    
# インデックスx,yを与えると、xとyの木を統合する関数
def union(x,y):
    # root_x, root_yは根のインデックス
    root_x = find_root(x)
    root_y = find_root(y)
    if root_x == root_y:
        return
    elif rank[root_x] > rank[root_y]: # 短い木(yの方)を長い木(xの方)に繋ぐ
        root[root_x] += root[root_y] # 要素数結合
        root[root_y] = root_x # 根を切り替え
    else:
        root[root_y] += root[root_x]
        root[root_x] = root_y
        
        if rank[root_x] == rank[root_y]:
            rank[root_y] += 1 # 新しい木の高さを1追加
            
for idx in range(M):
    union(xy[idx][0]-1, xy[idx][1]-1)
    
ans = 0
for i in range(N):
    if find_root(i) == find_root(p[i]-1):
        ans += 1
        
print(ans)
# Original solution
n, m = list(map(int, input().split()))
ps = list(map(int, input().split()))
ls = [list(map(int, input().split())) for _ in range(m)]


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = list(range(n + 1))
        self.ranks = [0 for _ in range(n + 1)]

    def get_root(self, x):
        if self.parents[x] == x:
            return x
        self.parents[x] = self.get_root(self.parents[x])
        return self.parents[x]

    def merge(self, x, y):
        x = self.get_root(x)
        y = self.get_root(y)
        if x != y:
            if self.ranks[x] < self.ranks[y]:
                self.parents[x] = y
            else:
                self.parents[y] = x
                if self.ranks[x] == self.ranks[y]:
                    self.ranks[x] += 1


uf = UnionFind(n)
for a, b in ls:
    uf.merge(a, b)
for i in range(1, n + 1):
    uf.get_root(i)
cs = uf.parents
s0 = {c: [] for c in set(cs[1:])}
s1 = {c: [] for c in set(cs[1:])}
for i in range(1, n + 1):
    c = cs[i]
    s0[c].append(ps[i - 1])
    s1[c].append(i)

res = 0
for c in set(cs[1:]):
    res += len(set(s0[c]) & set(s1[c]))
print(res)

# Optimized solution
n, m = list(map(int, input().split()))
ps = list(map(int, input().split()))
ls = [list(map(int, input().split())) for _ in range(m)]


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = list(range(n + 1))
        self.ranks = [0 for _ in range(n + 1)]

    def get_root(self, x):
        if self.parents[x] == x:
            return x
        self.parents[x] = self.get_root(self.parents[x])
        return self.parents[x]

    def merge(self, x, y):
        x = self.get_root(x)
        y = self.get_root(y)
        if x != y:
            if self.ranks[x] < self.ranks[y]:
                self.parents[x] = y
            else:
                self.parents[y] = x
                if self.ranks[x] == self.ranks[y]:
                    self.ranks[x] += 1


uf = UnionFind(n)
for a, b in ls:
    uf.merge(a, b)
res = 0
for i in range(1, n + 1):
    p0 = uf.get_root(i)
    p1 = uf.get_root(ps[i - 1])
    if p0 == p1:
        res += 1
print(res)
# 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 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 all_group_members(self):
        return {r: self.members(r) for r in self.roots()}
      
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))

uf = UnionFind(n)

for i in range(m):
  a,b = list(map(int,input().split()))
  uf.union(a-1,b-1)
values = list(uf.all_group_members().values())

ans = 0
for vs in values:
  s = set(P[v]-1 for v in vs)
  ans += len(s & (set(vs)))

print(ans)  

# Optimized solution
## TLE
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 same(self, x, y):
        return self.find(x) == self.find(y)
      
n,m = list(map(int,input().split()))
P = list(map(int,input().split()))

uf = UnionFind(n)

for i in range(m):
  a,b = list(map(int,input().split()))
  uf.union(a-1,b-1)

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

print(ans)
# Original solution
N, M = list(map(int, input().split()))
p = [int(i) for i in input().split()]
graph = [[] for _ in range(N+1)]
group = [0]*(N+1)
ans = 0
for _ in range(M):
    x, y = (int(i) for i in input().split())
    graph[x].append(y)
    graph[y].append(x)
for i, num in enumerate(p, 1):
    space = [i]
    for point in space:
        if group[point]:
            continue
        group[point] = i
        space.extend(graph[point])
    ans += (group[num] == group[i])
print(ans)

# Optimized solution
N, M = list(map(int, input().split()))
p = [int(i) for i in input().split()]
graph = [[] for _ in range(N+1)]
group = [0]*(N+1)
ans = 0
for _ in range(M):
    x, y = list(map(int, input().split()))
    graph[x].append(y)
    graph[y].append(x)
for i, num in enumerate(p, 1):
    space = [i]
    for point in space:
        if not group[point]:
            group[point] = i
            space.extend(graph[point])
    ans += (group[num] == group[i])
print(ans)
# Original solution
def main():
    n, m = list(map(int, input().split()))
    p = [0] + list(map(int, input().split()))
    cnt = 0
    global parent
    parent = list(range(n+1))
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if root(i) == root(p[i]):
            cnt += 1
    print(cnt)

def root(x):
    if parent[x] == x:
        return x
    parent[x] = root(parent[x])
    return parent[x]

def unite(x, y):
    root_x = root(x)
    if root_x != root(y):
        parent[root_x] = y

if __name__ == "__main__":
    main()

# Optimized solution
def main():
    n, m = list(map(int, input().split()))
    p = [0] + list(map(int, input().split()))
    cnt = 0
    global parent
    parent = list(range(n+1))
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i]):
            cnt += 1
    print(cnt)

def root(x):
    if parent[x] == x:
        return x
    parent[x] = root(parent[x])
    return parent[x]

def unite(x, y):
    root_x = root(x)
    if root_x != root(y):
        parent[root_x] = y

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

if __name__ == "__main__":
    main()
# Original solution
def main():
    p = [0] + list(map(int, input().split()))
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i]):
            cnt += 1
    print(cnt)

def root(x):
    if parent[x] == x:
        return x
    parent[x] = root(parent[x])
    return parent[x]

def unite(x, y):
    root_x = root(x)
    if root_x != root(y):
        parent[root_x] = y

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

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    parent = list(range(n+1))
    main()

# Optimized solution
def main():
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i-1]):
            cnt += 1
    print(cnt)
        
def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

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

def unite(x, y):
    x = root(x)
    y = root(y)
    if x != y:
        par[x] = y

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    par = [0] + [i for i in range(1, n+1)]
    main()
# Original solution
def main():
    p = [0] + list(map(int, input().split()))
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i]):
            cnt += 1
    print(cnt)

def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

def unite(x, y):
    root_x = root(x)
    if root_x != root(y):
        par[root_x] = y

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

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    par = list(range(n+1))
    main()

# Optimized solution
def main():
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i-1]):
            cnt += 1
    print(cnt)

def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

def unite(x, y):
    root_x = root(x)
    if root_x != root(y):
        par[root_x] = y

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

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    par = list(range(n+1))
    p = list(map(int, input().split()))
    main()
# Original solution
def main():
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i-1]):
            cnt += 1
    print(cnt)

def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

def unite(x, y):
    x = root(x)
    if x != root(y):
        par[x] = y

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

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    par = list(range(n+1))
    p = list(map(int, input().split()))
    main()

# Optimized solution
def main():
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i in range(1, n+1):
        if same(i, p[i]):
            cnt += 1
    print(cnt)
        
def root(x):
    if par[x] == x:
        return x
    par[x] = root(par[x])
    return par[x]

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

def unite(x, y):
    x = root(x)
    y = root(y)
    if x != y:
        par[x] = y

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    p = [0] + list(map(int, input().split()))
    par = list(range(n+1))
    main()
# Original solution
def main():
    cnt = 0
    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i, pi in enumerate(p, 1):
        if root(i) == root(pi):
            cnt += 1
    print(cnt)
        
def root(x):
    if parent[x] == x:
        return x
    parent[x] = root(parent[x])
    return parent[x]

def unite(x, y):
    x = root(x)
    y = root(y)
    if x != y:
        if rank[x] < rank[y]:
            parent[x] = y
        elif rank[x] > rank[y]:
            parent[y] = x
        else:
            parent[y] = x
            rank[x] += 1

if __name__ == "__main__":
    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    parent = list(range(n+1))
    rank = [0]*(n+1)
    main()


# Optimized solution
def main():
    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    parent = list(range(n+1))
    rank = [0]*(n+1)
    cnt = 0
    
    def root(x):
        if parent[x] == x:
            return x
        parent[x] = root(parent[x])
        return parent[x]
    
    def unite(x, y):
        x = root(x)
        y = root(y)
        if x != y:
            if rank[x] < rank[y]:
                parent[x] = y
            elif rank[x] > rank[y]:
                parent[y] = x
            else:
                parent[y] = x
                rank[x] += 1

    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i, pi in enumerate(p, 1):
        if root(i) == root(pi):
            cnt += 1
    print(cnt)

if __name__ == "__main__":
    main()
# Original solution
import sys
input = sys.stdin.buffer.readline

def main():
    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    parent = list(range(n+1))
    rank = [0]*(n+1)
    cnt = 0
    
    def root(x):
        if parent[x] == x:
            return x
        parent[x] = root(parent[x])
        return parent[x]
    
    def unite(x, y):
        x = root(x)
        y = root(y)
        if x != y:
            if rank[x] < rank[y]:
                parent[x] = y
            elif rank[x] > rank[y]:
                parent[y] = x
            else:
                parent[y] = x
                rank[x] += 1

    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i, pi in enumerate(p, 1):
        if root(i) == root(pi):
            cnt += 1
    print(cnt)

if __name__ == "__main__":
    main()


# Optimized solution
import sys
input = sys.stdin.buffer.readline

def main():
    n, m = list(map(int, input().split()))
    p = list(map(int, input().split()))
    parent = list(range(n+1))
    rank = [0]*(n+1)
    cnt = 0
    
    def root(x):
        if parent[x] == x:
            return x
        parent[x] = root(parent[x])
        return parent[x]
    
    def unite(x, y):
        x = root(x)
        y = root(y)
        if x != y:
            if rank[x] > rank[y]:
                parent[y] = x
            elif rank[x] < rank[y]:
                parent[x] = y
            else:
                parent[y] = x
                rank[x] += 1

    for _ in range(m):
        x, y = list(map(int, input().split()))
        unite(x, y)
    for i, pi in enumerate(p, 1):
        if root(i) == root(pi):
            cnt += 1
    print(cnt)

if __name__ == "__main__":
    main()
# Original solution
n,m=list(map(int,input().split()))
f=lambda x:int(x)-1
p=list(map(f,input().split()))
par=[j for j in range(n)]
def find(x):
  if x==par[x]:
    return x
  else:
    par[x]=find(par[x])
    return par[x]
 
def union(a,b):
  ra=find(a)
  rb=find(b)
  if ra!=rb:
    par[ra]=par[rb]
 
for i in range(m):
  v,w=list(map(f,input().split()))
  union(v,w)
 
ans=0
for j in range(n):
  if find(j)==find(p[j]):
    ans+=1
print(ans)

# Optimized solution
n,m=list(map(int,input().split()))
p=list(map(int,input().split()))
par=[i for i in range(n)]
 
def find(x):
  if par[x]==x:
    return par[x]
  else:
    par[x]=find(par[x])
    return par[x]
 
def union(x,y):
  fx=find(x)
  fy=find(y)
  if fx!=fy:
    par[fx]=fy
 
f=lambda x:int(x)-1
for mm in range(m):
  x,y=list(map(f,input().split()))
  union(x,y)
 
ans=0
for i in range(n):
  if find(p[i]-1)==find(i):
    ans+=1
print(ans)