// Original C++ solution (slower):
#include <bits/stdc++.h>

#define INF 1000000000

#define ll long long

using namespace std;







// ============union_find_tree===============

ll MAX_N = 100000;

vector<ll> par(MAX_N);//MAX_N == num of node

vector<ll> tree_rank(MAX_N);



void init(ll n)

{

  for (ll i = 0; i < n; ++i)

  {

    par.at(i) = i;

    tree_rank.at(i) = 0;

  }

}



ll find(ll x)

{

  if (par.at(x) == x)

  {

    return x;

  }

  else

  {

    return par.at(x) = find(par.at(x));

  }

}



void unite(ll x, ll y)

{

  x = find(x);

  y = find(y);

  if (x == y)

  {

    return;

  }

  if (tree_rank.at(x) < tree_rank.at(y))

  {

    par.at(x) = y;

  }

  else

  {

    par.at(y) = x;

    if (tree_rank.at(x) == tree_rank.at(y))

    {

      tree_rank.at(x)++;

    }

  }

}



bool same(ll x, ll y)

{

  return find(x) == find(y);

}

// =======================================





int main()

{

  ll N, M;

  cin >> N >> M;

  vector<ll> p(N);

  for (ll i = 0; i < N; ++i)

  {

    cin >> p.at(i);

  }

  init(N);

  for (ll i = 0; i < M; ++i)

  {

    ll x, y;

    cin >> x >> y;

    unite(x - 1, y - 1);

  }



  ll ans = 0;

  for (ll i = 0; i < N; ++i)

  {

    if (same(p.at(i) - 1, i))

    {

      ans += 1;

    }

  }

  cout << ans << endl;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#define INF 2000000000000000000

#define ll long long

#define pll pair<ll, ll>

using namespace std;



// ===========Disjoint Set Union================

struct dsu {

  public:

    dsu() : _n(0) {}

    dsu(int n) : _n(n), parent_or_size(n, -1) {}



    int merge(int a, int b) {

        assert(0 <= a && a < _n);

        assert(0 <= b && b < _n);

        int x = leader(a), y = leader(b);

        if (x == y) return x;

        if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);

        parent_or_size[x] += parent_or_size[y];

        parent_or_size[y] = x;

        return x;

    }



    bool same(int a, int b) {

        assert(0 <= a && a < _n);

        assert(0 <= b && b < _n);

        return leader(a) == leader(b);

    }



    int leader(int a) {

        assert(0 <= a && a < _n);

        if (parent_or_size[a] < 0) return a;

        return parent_or_size[a] = leader(parent_or_size[a]);

    }



    int size(int a) {

        assert(0 <= a && a < _n);

        return -parent_or_size[leader(a)];

    }



    std::vector<std::vector<int>> groups() {

        std::vector<int> leader_buf(_n), group_size(_n);

        for (int i = 0; i < _n; i++) {

            leader_buf[i] = leader(i);

            group_size[leader_buf[i]]++;

        }

        std::vector<std::vector<int>> result(_n);

        for (int i = 0; i < _n; i++) {

            result[i].reserve(group_size[i]);

        }

        for (int i = 0; i < _n; i++) {

            result[leader_buf[i]].push_back(i);

        }

        result.erase(

            std::remove_if(result.begin(), result.end(),

                           [&](const std::vector<int>& v) { return v.empty(); }),

            result.end());

        return result;

    }



  private:

    int _n;

    // root node: -1 * component size

    // otherwise: parent

    std::vector<int> parent_or_size;

};

// =======================================



int main() {

  ios::sync_with_stdio(false);

  cin.tie(nullptr);

  ll N, M;

  cin >> N >> M;

  vector<ll> A(N);

  for (ll i = 0; i < N; ++i) {

    cin >> A.at(i);

    A.at(i) -= 1;

  }

  dsu d(N);

  for (ll i = 0; i < M; ++i) {

    ll x, y;

    cin >> x >> y;

    x -= 1, y -= 1;

    d.merge(x, y);

  }

  ll ans = 0;

  for (ll i = 0; i < N; ++i) {

    if (d.leader(A.at(i)) == d.leader(i)) {

      ans += 1;

    }

  }

  cout << ans << "\n";

}


// Fastest known solution for this problem: