Problem:
Score : 400 points

Problem Statement

We have a permutation of the integers from 1 through N, p_1, p_2, .., p_N.
We also have M pairs of two integers between 1 and N (inclusive), represented as (x_1,y_1), (x_2,y_2), .., (x_M,y_M).
AtCoDeer the deer is going to perform the following operation on p as many times as desired so that the number of i (1 ≤ i ≤ N) such that p_i = i is maximized:

Choose j such that 1 ≤ j ≤ M, and swap p_{x_j} and p_{y_j}.

Find the maximum possible number of i such that p_i = i after operations.

Constraints

2 ≤ N ≤ 10^5

1 ≤ M ≤ 10^5

p is a permutation of integers from 1 through N.

1 ≤ x_j,y_j ≤ N

x_j ≠ y_j

If i ≠ j, \{x_i,y_i\} ≠ \{x_j,y_j\}.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
p_1 p_2 .. p_N
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the maximum possible number of i such that p_i = i after operations.

Sample Input 1

5 2
5 3 1 4 2
1 3
5 4

Sample Output 1

2

If we perform the operation by choosing j=1, p becomes 1 3 5 4 2, which is optimal, so the answer is 2.

Sample Input 2

3 2
3 2 1
1 2
2 3

Sample Output 2

3

If we perform the operation by, for example, choosing j=1, j=2, j=1 in this order, p becomes 1 2 3, which is obviously optimal.
Note that we may choose the same j any number of times.

Sample Input 3

10 8
5 3 6 8 7 10 9 1 2 4
3 1
4 1
5 9
2 5
6 5
3 5
8 9
7 9

Sample Output 3

8

Sample Input 4

5 1
1 2 3 4 5
1 5

Sample Output 4

5

We do not have to perform the operation.

Solution in Java (OpenJDK 11.0.6) (judge verdict: Time Limit Exceeded)

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.Arrays;
import java.util.AbstractCollection;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.ArrayList;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Equals solver = new Equals();
        solver.solve(1, in, out);
        out.close();
    }

    static class Equals {
        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            int[] p = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                p[i] = in.nextInt();
            }

            List<List<Node>> graph = new ArrayList<>();
            for (int i = 0; i <= n; i++) {
                graph.add(new ArrayList<>());
            }

            for (int i = 1; i <= m; i++) {
                int x = in.nextInt();
                int y = in.nextInt();
                graph.get(x).add(new Node(y, 1));
                graph.get(y).add(new Node(x, 1));
            }
            long result = 0;
            for (int i = 1; i <= n; i++) {
                int goal = p[i];
                int[] dis = dijkstra(i, graph);
                if (dis[goal] != Integer.MAX_VALUE) {
                    result++;
                }
            }
            out.println(result);

        }

        int[] dijkstra(int start, List<List<Node>> graph) {
            int n = graph.size();

            Equals.Color[] colors = new Equals.Color[n];
            int[] distance = new int[n];
            Arrays.fill(colors, Equals.Color.WHITE);
            Arrays.fill(distance, Integer.MAX_VALUE);

            // 昇順
            PriorityQueue<Pair> pq = new PriorityQueue<>(n, (o1, o2) -> Integer.compare(o1.weight, o2.weight));

            distance[start] = 0;
            pq.add(new Pair(0, start));
            colors[start] = Equals.Color.GRAY;

            while (!pq.isEmpty()) {
                Pair p = pq.poll();
                colors[p.node] = Equals.Color.BLACK;
                if (distance[p.node] < p.weight) {
                    continue;
                }
                for (int i = 0; i < graph.get(p.node).size(); i++) {
                    Node next = graph.get(p.node).get(i);

                    if (colors[next.dist] == Equals.Color.BLACK) {
                        continue;
                    }
                    int cost = distance[p.node] + next.weight;
                    if (distance[next.dist] > cost) {
                        distance[next.dist] = cost;
                        pq.add(new Pair(cost, next.dist));
                        colors[next.dist] = Equals.Color.GRAY;
                    }
                }
            }
            return distance;
        }

        public enum Color {
            WHITE,
            GRAY,
            BLACK,
            ;
        }

        class Node {
            public final Integer dist;
            public final Integer weight;

            Node(Integer dist, Integer weight) {
                this.dist = dist;
                this.weight = weight;
            }

        }

        class Pair {
            public final Integer weight;
            public final Integer node;

            public Pair(Integer weight, Integer node) {
                this.weight = weight;
                this.node = node;
            }

        }

    }
}