#include <bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set1 = tree<long long, null_type, less_equal<long long>, rb_tree_tag, tree_order_statistics_node_update>;
#define op() \
ios_base::sync_with_stdio(0); \
cin.tie(0); \
cout.tie(0);
#define yes cout << "YES\n";
#define no cout << "NO\n";
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) ((a * b) / gcd(a, b))
#define PI 2.0 * acos(0.0)
#define Dpos(n) fixed << setprecision(n)
typedef int ll;
typedef long double ld;
typedef vector<ll> vl;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
const ll MOD = 1e9 + 7;
const ll N = 1e5 + 1;
vl par(N), level(N), v1(N);
ll dsu_find(ll node)
{
if (par[node] == -1)
return node;
return par[node] = dsu_find(par[node]);
}
void dsu_union_by_level(ll node1, ll node2)
{
ll leader1 = dsu_find(node1);
ll leader2 = dsu_find(node2);
if (level[leader1] > level[leader2])
par[leader2] = leader1;
else if (level[leader1] < level[leader2])
par[leader1] = leader2;
else
{
par[leader1] = leader2;
level[leader2]++;
}
}
void solve()
{
ll n, q, i, x, y, ans = 0;
cin >> n >> q;
for (i = 1; i <= n; i++)
{
par[i] = -1, level[i] = 0;
cin >> v1[i];
}
for (i = 1; i <= q; i++)
{
cin >> x >> y;
dsu_union_by_level(x, y);
}
for (i = 1; i <= n; i++)
{
if (i == v1[i])
{
ans++;
continue;
}
x = dsu_find(i);
if (x == -1)
continue;
y = dsu_find(v1[i]);
if (y == -1)
continue;
if (x == y)
ans++;
}
cout << ans << endl;
}
int main()
{
op() int tc = 1;
cin >> tc;
for (int t = 1; t <= tc; t++)
{
// cout << "Case " << t << ": ";
solve();
}
}