import core.bitop, std.algorithm, std.ascii, std.bigint, std.conv, std.math,
    std.functional, std.numeric, std.range, std.stdio, std.string, std.random,
    std.typecons, std.container, std.format;

// dfmt off
T lread(T = long)(){return readln.chomp.to!T();}
T[] lreads(T = long)(long n){return generate(()=>readln.chomp.to!T()).take(n).array();}
T[] aryread(T = long)(){return readln.split.to!(T[])();}
void scan(TList...)(ref TList Args){auto line = readln.split();
foreach (i, T; TList){T val = line[i].to!(T);Args[i] = val;}}
alias sread = () => readln.chomp();enum MOD = 10 ^^ 9 + 7;
alias PQueue(T, alias less = "a<b") = BinaryHeap!(Array!T, less);
// dfmt on

void main()
{
    long N, M;
    scan(N, M);
    auto P = aryread();
    auto uf = UnionFind(N + 1);
    foreach (i; 0 .. M)
    {
        long X, Y;
        scan(X, Y);
        uf.unite(X, Y);
    }
    long ans;
    foreach (i; 0 .. N)
        ans += (uf.find(i + 1) == uf.find(P[i]));
    writeln(ans);
}

alias UnionFind = UnionFindImpl!long;
struct UnionFindImpl(T)
{
    T[] _rank, _data, _size;
    this(long n)
    {
        _rank = new long[](n);
        _size = new long[](n);
        _size[] = 1;
        _data = iota!T(n).array();
    }

    T find(T x)
    {
        if (_data[x] == x)
            return x;
        T r = _data[x] = this.find(_data[x]);
        return r;
    }

    void unite(T x, T y)
    {
        T rx = this.find(x), ry = this.find(y);
        if (rx == ry)
            return;
        _size[rx] = _size[ry] = (_size[rx] + _size[ry]);
        if (_rank[rx] == _rank[ry])
        {
            _data[rx] = ry;
            _rank[ry]++;
        }
        else if (_rank[rx] < _rank[ry])
            _data[rx] = ry;
        else
            _data[ry] = rx;
    }

    T size(T x)
    {
        return _size[this.find(x)];
    }
}
