stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;



using ll = long long;

const int MAX_N = 1e5 + 1;

int n, m;

int p[MAX_N], used[MAX_N];

bool visited1[MAX_N], visited2[MAX_N];

vector<int> g[MAX_N];



void Input() {

    scanf("%d %d", &n, &m);



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

        scanf("%d", &p[i]);

        --p[i];

    }

    for (int i = 0, x, y; i < m; ++i) {

        scanf("%d %d", &x, &y);

        g[x - 1].push_back(y - 1);

        g[y - 1].push_back(x - 1);

    }



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

        visited1[i] = visited2[i] = false;

}



void Dfs1(const int cur, const int gr) {

    visited1[cur] = true;

    used[p[cur]] = gr;



    for (auto dst : g[cur]) {

        if (visited1[dst]) continue;

        Dfs1(dst, gr);

    }

}



int Dfs2(const int cur, const int gr) {

    visited2[cur] = true;



    int res = (used[cur] == gr ? 1 : 0);

    for (auto dst : g[cur]) {

        if (visited2[dst]) continue;

        res += Dfs2(dst, gr);

    }



    return res;

}





int Solve() {

    int res = 0, gr = 1;



    for (int v = 0; v < n; ++v) {

        if (visited1[v]) continue;

        Dfs1(v, gr);

        res += Dfs2(v, gr);

        ++gr;

    }



    return res;

}



int main() {

    Input();

    printf("%d\n", Solve());



    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.4724060040969547x):
#include <bits/stdc++.h>



using namespace std;



class UnionFind {

public:

    UnionFind(int size) : data(size, -1) {}



    bool UnionSet(int x, int y) {

        x = root(x); y = root(y);

        if (x != y) {

            if (data[y] < data[x]) swap(x, y);

            data[x] += data[y]; data[y] = x;

        }

        return x != y;

    }

    bool FindSet(int x, int y) { return root(x) == root(y); }

    int size(int x) { return -data[root(x)]; }



private:

    std::vector<int> data;

    int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }

};





int main() {

    cin.tie(0); ios::sync_with_stdio(false);



    int n, m;



    cin >> n >> m;

    vector<int> p(n);

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

        cin >> p[i];

        --p[i];

    }



    UnionFind uf(n);

    for (int i = 0, x, y; i < m; ++i) {

        cin >> x >> y;

        uf.UnionSet(x - 1, y - 1);

    }



    int cnt = 0;

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

        if (uf.FindSet(i, p[i])) ++cnt;



    cout << cnt << endl;



    return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h> 

using namespace std ;



const int maxn = 1e5 + 7 ;



vector < int > g[ maxn ] ;

vector < bool > visited( maxn , false ) ;

vector < int > s_num( maxn ) ;





void dfs ( int u , int set )

{

    visited[u] = true ;

    s_num[u] = set ;

    for (  int j = 0 ; j < g[u] .size() ; j++  )

    {

        int v = g[u][j];

         if ( ! visited[v] )

         {

             dfs ( v , set );

         }

    }

}





int main ( )

{

     int n , m , set = 0 ;

     cin >> n >> m ;

     vector < int > a ( n ) ;

    

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

     {

         cin >> a[i] ; 

     }

    

    for ( int i = 0 ; i < m ; i++ )

    {

        int x , y ;

        cin >> x >> y;

        g[x].push_back( y ) ;

        g[y].push_back( x ) ;

    }

    

    int ss = 1 ;

    for ( int i = 1 ; i <= n ; i++ )

    {

        if ( !visited [ i ] )

        {

            dfs ( i , ss ) ;

            ss++;

        }

    }

    int ans = 0 ;

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

    {

        if ( s_num [ i + 1 ] == s_num[ a[i] ] || a[i] == i+1 )

        {

            ans++ ;

        }

    }

    cout << ans << endl ;

    return 0 ;

}

// Faster C++ solution for the same problem (measured speedup: 2.1772961193334495x):
#include<bits/stdc++.h> 

using namespace std ;



const int maxn = 1e5 + 7 ;

vector < int > parent( maxn ) ;

vector < int > rnk ( maxn );





int find_parent ( int x )

{

    if ( parent[x] != x ) return find_parent (parent[x] ) ;

    return x ;

}



void dsu ( int u , int v )

{

     u = find_parent( u ) ;

     v = find_parent ( v ) ;

    

    if ( u != v ) 

    {

         if ( rnk [u] == rnk [v] )

         {

           parent [ u ] = v ;

           rnk [ v ] ++ ;

         }

        else if ( rnk [u] > rnk [v] )

        {

            parent [ v ] =  u ;

        }

        else 

        {

            parent [ u ] = v ;

        }

    }

}



int main ( )

{

    int n , m ;

    cin >> n >> m ;

    vector < int > a(n) ;

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

    {

         cin >> a[i] ;

         parent [ i +1 ] = i + 1 ;

    }

    

    for ( int i = 0 ; i < m ; i++ )

    {

         int x , y ;

         cin >> x >> y ;

         dsu ( x , y ) ;

    }

    

    int ans = 0 ;

    

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

    {

        if ( find_parent ( i+1 ) == find_parent ( a[ i ] ) ) ans ++ ;

    }

    cout << ans << endl ;

}
// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;



vector<int> group[100010];

int n, m;

int f[100010], z[100010], vis[100010], a[100010];

int fin(int x)

{

    return (f[x] == x) ?  x : (f[x] = fin(f[x]));

}

int main()

{

    scanf("%d%d", &n, &m);

    for(int i=1; i<=n; i++)

        scanf("%d", &z[i]);



    for(int i=1; i<=n; i++)

        f[i] = i;

    for(int i=1; i<=m; i++)

    {

        int x, y;

        scanf("%d%d", &x, &y);

        int fx = fin(x);

        int fy = fin(y);

        if (fx != fy)

        {

            f[fy] = fx;

        }

    }



    for(int i=1; i<=n; i++)

        group[i].clear();

    for(int i=1; i<=n; i++)

    {

        int fx = fin(i);

        group[fx].push_back(i);

    }



    memset(vis, 0, sizeof(vis));

    int ans = 0;

    for(int i=1; i<=n; i++)

    {

        int l = group[i].size();

        if (l != 0)

        {

            for(int j=0; j<l; j++)

            {

                int x = group[i][j];

                vis[x] = i;

                a[j] = z[x];

            }

            for(int j=0; j<l; j++)

                if (vis[a[j]] == i) ans++;

        }

    }

    cout<<ans<<endl;

}


// Faster C++ solution for the same problem (measured speedup: 3.9125511611322623x):
#include <iostream>

#include <cstdio>

#include <queue>

#include <cstring>

#include <map>

#include <cmath>

#include <algorithm>

#include <stack>

using namespace std;

int fa[100010];

int finds(int x){

    if(fa[x] == x) return x;

    fa[x] = finds(fa[x]);

    return fa[x];

}

void join(int x,int y){

    int fx = finds(x);

    int fy = finds(y);

    if(fx != fy) fa[fx] = fy;

}

int p[100005];

int a[100005],b[100005];

int main()

{

    int n,m;

    cin >> n >> m;

    for(int i = 1;i <= n;++i) scanf("%d",&p[i]);

    for(int i = 1;i <= n;++i) fa[i] = i;

    for(int i = 1;i <= m;++i){

        scanf("%d%d",&a[i],&b[i]);

        join(a[i],b[i]);

    }

    int cnt = 0;

    for(int i = 1;i <= n;++i){

        if(finds(p[i]) == finds(i)) cnt++;

    }

    cout << cnt << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;



vector<int> group[100010];

int n, m;

int f[100010], z[100010], vis[100010], a[100010];

int fin(int x)

{

    return (f[x] == x) ?  x : (f[x] = fin(f[x]));

}

int main()

{

    scanf("%d%d", &n, &m);

    for(int i=1; i<=n; i++)

        scanf("%d", &z[i]);



    for(int i=1; i<=n; i++)

        f[i] = i;

    for(int i=1; i<=m; i++)

    {

        int x, y;

        scanf("%d%d", &x, &y);

        int fx = fin(x);

        int fy = fin(y);

        if (fx != fy)

        {

            f[fy] = fx;

        }

    }



    for(int i=1; i<=n; i++)

        group[i].clear();

    for(int i=1; i<=n; i++)

    {

        int fx = fin(i);

        group[fx].push_back(i);

    }



    memset(vis, 0, sizeof(vis));

    int ans = 0;

    for(int i=1; i<=n; i++)

    {

        int l = group[i].size();

        if (l != 0)

        {

            for(int j=0; j<l; j++)

            {

                int x = group[i][j];

                vis[x] = i;

                a[j] = z[x];

            }

            for(int j=0; j<l; j++)

                if (vis[a[j]] == i) ans++;

        }

    }

    cout<<ans<<endl;

}


// Faster C++ solution for the same problem (measured speedup: 3.9733223267693174x):
#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <iostream>

using namespace std;

typedef long long ll;

const int mx = 1e5+100;

int father[mx],n,m,p[mx];

int fi(int a)

{

    int x=a,j;

    while(father[x]!=x)

        x=father[x];

    while(a!=x){

        j=father[a];

        father[a]=x;

        a=j;

    }

    return x;

}

void join(int a,int b)

{

    int fa=fi(a);

    int fb=fi(b);

    father[fa]=father[b];

}

void init()

{

    for(int i=1;i<=n;i++)

        father[i]=i;

}

int main()

{

    while(~scanf("%d%d",&n,&m)){

        init();

        for(int i=1;i<=n;i++)

            scanf("%d",&p[i]);

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

            int x,y;

            scanf("%d%d",&x,&y);

            join(x,y);

        }

        int ans=0;

        for(int i=1;i<=n;i++){

            if(fi(i)==fi(p[i]))

                ans++;

        }

        printf("%d\n",ans);

    }

    return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;



vector<int> group[100010];

int n, m;

int f[100010], z[100010], vis[100010], a[100010];

int fin(int x)

{

    return (f[x] == x) ?  x : (f[x] = fin(f[x]));

}

int main()

{

    scanf("%d%d", &n, &m);

    for(int i=1; i<=n; i++)

        scanf("%d", &z[i]);



    for(int i=1; i<=n; i++)

        f[i] = i;

    for(int i=1; i<=m; i++)

    {

        int x, y;

        scanf("%d%d", &x, &y);

        int fx = fin(x);

        int fy = fin(y);

        if (fx != fy)

        {

            f[fy] = fx;

        }

    }



    for(int i=1; i<=n; i++)

        group[i].clear();

    for(int i=1; i<=n; i++)

    {

        int fx = fin(i);

        group[fx].push_back(i);

    }



    memset(vis, 0, sizeof(vis));

    int ans = 0;

    for(int i=1; i<=n; i++)

    {

        int l = group[i].size();

        if (l != 0)

        {

            for(int j=0; j<l; j++)

            {

                int x = group[i][j];

                vis[x] = i;

                a[j] = z[x];

            }

            for(int j=0; j<l; j++)

                if (vis[a[j]] == i) ans++;

        }

    }

    cout<<ans<<endl;

}


// Faster C++ solution for the same problem (measured speedup: 1.1045131407532867x):
//

// Created by Mahmoud Rashad on 11/27/19.

//



#include <bits/stdc++.h>





using namespace std;



typedef vector<int> vi;

typedef pair<int, int> ii;

typedef vector<pair<ii, ii>> vii;



const int MAXN = (int)1e5 + 5;

int p[MAXN];

bool vis[MAXN];

vector<int> adjList[MAXN];

set<int> st;



void dfs(int u) {

    vis[u] = 1;

    st.insert(u);

    for (int v : adjList[u])

        if (!vis[v])

            dfs(v);



}





int main() {

#ifndef ONLINE_JUDGE

//    freopen("input.txt", "r", stdin);

//    freopen("output.out", "w", stdout);

#endif

    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0), cout.precision(10), cout << fixed;



    int n, m;

    cin >> n >> m;

    for (int i = 1; i <= n; ++i) {

        cin >> p[i];

    }



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

        int u, v;

        cin >> u >> v;

        adjList[u].push_back(v);

        adjList[v].push_back(u);

    }



    int ans = 0;

    for (int i = 1; i <= n; ++i) {

        if (!vis[i]) {

            dfs(i);

            for (auto it : st) {

//                cout << it << endl;

                if (st.find(p[it]) != st.end())

                    ++ans;

            }

            st.clear();

        }

    }



    cout << ans << '\n';



    return 0;

}
// Slower C++ solution:
#include <iostream>

#include <vector>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef pair<ll, ll> P;



#define MOD 1000000007

#define REP(i, N) for (int i = 0; i < N; ++i)

#define REP1(i, N) for (int i = 1; i <= N; ++i)

#define RREP(i, N) for (int i = N - 1; i >= 0; --i)

#define ALL(a) a.begin(), a.end()



// Union-Find

vector<int> parent(100001);



void init(int n)

{

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

    parent[i] = i;

}



int root(int x)

{

  if (parent[x] == x)

    return x;

  else

    return parent[x] = root(parent[x]);

}



bool same(int x, int y)

{

  return root(x) == root(y);

}



void unite(int x, int y)

{

  x = root(x);

  y = root(y);

  if (x == y)

    return;

  parent[x] = y;

}



int main()

{

  int N, M;

  cin >> N >> M;

  vector<int> p(N);

  REP(i, N)

  {

    cin >> p[i];

    p[i]--;

  }

  vector<int> x(M), y(M);

  REP(i, M)

  {

    cin >> x[i] >> y[i];

    x[i]--, y[i]--;

  }

  init(N);

  REP(i, M)

  unite(p[x[i]], p[y[i]]);

  int ans = 0;

  REP(i, N)

  {

    if (same(i, p[i]))

      ans++;

  }

  cout << ans << endl;

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.4094845709187664x):
#include <algorithm>

#include <iostream>

#include <vector>



using namespace std;



typedef long long ll;

typedef pair<ll, ll> P;



#define MOD 1000000007

#define REP(i, N) for (int i = 0; i < N; ++i)

#define REP1(i, N) for (int i = 1; i <= N; ++i)

#define RREP(i, N) for (int i = N - 1; i >= 0; --i)

#define ALL(a) a.begin(), a.end()



struct UnionFind {

  vector<int> par;

  vector<int> sz;

  UnionFind(int n) { init(n); }



  void init(int n) {

    par.resize(n);

    sz.resize(n);

    REP(i, n) {

      par[i] = i;

      sz[i] = 1;

    }

  }



  int find(int x) {

    if (par[x] == x)

      return x;

    else

      return par[x] = find(par[x]);

  }



  void unite(int x, int y) {

    x = find(x);

    y = find(y);

    if (x == y) return;

    if (sz[x] < sz[y]) {

      par[x] = y;

      sz[y] += sz[x];

    } else {

      par[y] = x;

      sz[x] += sz[y];

    }

  }



  bool same(int x, int y) { return find(x) == find(y); }



  int size(int x) { return sz[find(x)]; }

};



int main() {

  int n, m;

  cin >> n >> m;

  int p[n];

  REP(i, n) {

    cin >> p[i];

    p[i]--;

  }

  UnionFind uf(n);

  REP(i, m) {

    int x, y;

    cin >> x >> y;

    x--, y--;

    uf.unite(x, y);

  }

  int ans = 0;

  REP(i, n) {

    if (uf.same(i, p[i])) ans++;

  }

  cout << ans << endl;

  return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#include <algorithm>

using namespace std;

const int maxn =2e5+9;

int a[maxn];

int fa[maxn];

int fi(int x){

    if(fa[x]== x) return x;

    return fa[x] = fi(fa[x]);

}

void uniun(int u,int v){

    int fu = fi(u);

    int fv = fi(v);

    if(fu!=fv){

        fa[fu] = fv;

    }

}

int main()

{

   // string nn = "1234366";

   // cout<<nn.substr(1,2);



    int n,m;

    while(~scanf("%d%d",&n,&m)){

        for(int i=1;i<=n;i++){

            scanf("%d",&a[i]);

            fa[i] = i;

        }

        for(int i=1;i<=m;i++){

            int u,v;

            scanf("%d%d",&u,&v);

            uniun(u,v);

        }

        int cnt = 0;

        for(int i=1;i<=n;i++){

            int tmp = a[i];

            if(fi(a[i])==fi(i)){

                cnt++;

            }

        }

        printf("%d\n",cnt);

    }

}


// Faster C++ solution for the same problem (measured speedup: 5.109283504956918x):
#include<cstdio>

using namespace std;

int N,M,P[100005],bb[100005],ans;

int find(int x)

{

    if(bb[x]!=x)

   	bb[x]=find(bb[x]);

    return bb[x];

}

void hb(int x,int y)

{

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

	if(a!=b)

	bb[b]=a;

	return ;

}

int main()

{

	scanf("%d %d",&N,&M);

	for(int i=1;i<=N;i++)

	{

		bb[i]=i;

		scanf("%d",&P[i]);

	}

	for(int i=1,a,b;i<=M;i++)

	{

		scanf("%d %d",&a,&b);

		hb(a,b);

	}

	for(int i=1;i<=N;i++)

	{

		if(find(i)==find(P[i]))

		ans++;

	}

	printf("%d",ans);

	return 0;

}
// Slower C++ solution:
#include<iostream>

#include<stdio.h>

#include<cstring>

using namespace std;

int num[100010];

int father[100010];	

int n,m;

int a,b;

int findfa(int a){

	if(father[a]==a)

		return father[a];

	else{

		father[a] = findfa(father[a]);

		return father[a];

	}

}

void doit(int a,int b){

	if(father[a]==-1&&father[b]==-1){

		father[b] = b;

		father[a] = b;

	}

	else if(father[a]==-1&&father[b]!=-1){

		father[a] = findfa(b);

	}

	else if(father[a]!=-1&&father[b]==-1){

		father[b] = findfa(a);

	}

	else if(father[a]!=-1&&father[b]!=-1){

		father[findfa(a)] = findfa(b);

		father[a] = findfa(b);

	}

}



int main(){

	memset(num,0,sizeof(num));

	memset(father,-1,sizeof(father));

	cin>>n>>m;

	for(int i=1;i<=n;i++)

		cin>>num[i];

	for(int j=0;j<m;j++){

		cin>>a>>b;

		doit(a,b);

	}

	int res = 0;

	for(int i=1;i<=n;i++){

		if(father[i]==-1)

			father[i] = i;

	}

	for(int i=1;i<=n;i++){

		if(findfa(i)- findfa(num[i])==0)

			res++;

	}

	cout<<res<<endl;

}

// Faster C++ solution for the same problem (measured speedup: 1.2770621692554522x):
#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5+5;

int pa[maxn];

int f(int x) {

    return x == pa[x] ? x : (pa[x] = f(pa[x]));

}

void un(int x, int y) {

    int px = f(x);

    int py = f(y);

    if (px != py) {

        pa[px] = py;

    }

}

int main() {

    int n, m;

    cin >> n >> m;

    vector<int> nums(n+1);

    for (int i = 1; i <= n; i++) {

        cin >> nums[i];

    }

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

        pa[i] = i;

    }

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

        int x, y;

        cin >> x >> y;

        un(x, y);

    }

    int ans = 0;

    for (int i = 1; i <= n; i++) {

        if (f(nums[i]) == f(i)) {

            ans++;

        }

    }

    cout << ans << "\n";

    return 0;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;



const int N = 1e5 + 10;



vector <int> G[N];

vector <int> sav;

int a[N], rec[N];



void dfs(int x, int id){

	rec[x] = id;

	sav.push_back(a[x]);

	for (int i = 0; i < (int)G[x].size(); i++){

		if (!rec[G[x][i]]) dfs(G[x][i], id);

	}

}



int main(){

	int n, m, u, v, ans;

	scanf("%d %d",&n,&m);

	for (int i = 1; i <= n; i++) scanf("%d",&a[i]);

	for (int i = 1; i <= m; i++){

		scanf("%d %d",&u,&v);

		G[u].push_back(v);

		G[v].push_back(u);

	}

	memset(rec, 0, sizeof(rec));

	ans = 0;

	for (int i = 1; i <= n; i++){

		if (!rec[i]){

			sav.clear();

			dfs(i, i);

			for (int j = 0; j < (int)sav.size(); j++){

				if (rec[sav[j]] == i) ans++;

			}

		}

	}

	printf("%d\n", ans);

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.1035780358144145x):
#include <bits/stdc++.h>

#define ll long long



using namespace std;



int n,m;

int p[100010];

vector<int> graf[100010];

int mark[100010];

int flag=1;



void bfs(int c)

{

    if(mark[c]==0)

        mark[c]=flag;

    else

        return;

    for(int i=0;i<graf[c].size();i++)

        if(mark[graf[c][i]]==0)

            bfs(graf[c][i]);

}



int main()

{

	ios::sync_with_stdio(false);

	cin.tie(0);



    cin>>n>>m;

    for(int i=1;i<=n;i++)

        cin>>p[i];

    int x,y;

    for(int i=0;i<m;i++)

    {

        cin>>x>>y;

        graf[x].push_back(y);

        graf[y].push_back(x);

    }



    int sol=0;

    for(int i=1;i<=n;i++)

    {

        if(mark[i]==0)

            bfs(i), flag++;

    }

    for(int i=1;i<=n;i++)

        if(mark[p[i]]==mark[i])

            sol++;

    cout<<sol;

	return 0;

}
// Slower C++ solution:
#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;



struct path

{

	int nex,to;

}edge[200005];



int head[100005],done[100005],total,number[100005],ok[100005],now;



inline void addedge(int nex, int to)

{

	edge[total].nex = head[nex];

	edge[total].to = to;

	head[nex] = total++;

}



void dfs(int point)

{

	ok[number[point]] = now;

	done[point] = now;

	for (int i = head[point]; i != -1; i = edge[i].nex)

	{

		if (!done[edge[i].to])

		{

			dfs(edge[i].to);

		}

	}

}



int main()

{

	int n,m,a,b,answer;

	answer = 0;

	scanf("%d%d",&n,&m);

	memset(head,-1,sizeof(head));

	for (int i = 1; i <= n; i++)

	{

		scanf("%d",&number[i]);

	}

	for (int i = 0; i < m; i++)

	{

		scanf("%d%d",&a,&b);

		addedge(a,b);

		addedge(b,a);

	}

	for (int i = 1; i <= n; i++)

	{

		if (!done[i])

		{

			now++;

			dfs(i);

		}

	}

	for (int i = 1; i <= n; i++)

	{

		answer += (done[i] == ok[i]);

	}

	printf("%d\n",answer);

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.357034650966607x):
#include <bits/stdc++.h>



void optimize_cpp_stdio() {

    std::ios::sync_with_stdio(false);

    std::cout.tie(nullptr);

    std::cin.tie(nullptr);

}



int main() {

    optimize_cpp_stdio();

    int n, m;

    std::cin >> n >> m;

    std::vector<int> a(n);

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

        std::cin >> a[i];

        --a[i];

    }

    std::vector<std::vector<int>> G(n);

    for (int i = 0, u, v; i < m; i++) {

        std::cin >> u >> v;

        G[--u].push_back(--v);

        G[v].push_back(u);

    }

    int ans = 0;

    std::vector<bool> vis(n);

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

        if (vis[i]) continue;

        std::vector<int> index, value;

        std::queue<int> q({i});

        vis[i] = true;

        for (; !q.empty(); q.pop()) {

            int u = q.front();

            index.push_back(u);

            value.push_back(a[u]);

            for (int v : G[u]) {

                if (vis[v]) continue;

                vis[v] = true;

                q.push(v);

            }

        }

        std::sort(index.begin(), index.end());

        for (int it : value)

            ans += std::binary_search(index.begin(), index.end(), it);

    }

    std::cout << ans << "\n";

    return 0;

}
// Slower C++ solution:
#include<iostream>

#include<stdio.h>

#include<cstring>

using namespace std;

int num[100010];

int father[100010];	

int n,m;

int a,b;

int findfa(int a){

	if(father[a]==a)

		return father[a];

	else{

		father[a] = findfa(father[a]);

		return father[a];

	}

}

void doit(int a,int b){

	if(father[a]==-1&&father[b]==-1){

		father[b] = b;

		father[a] = b;

	}

	else if(father[a]==-1&&father[b]!=-1){

		father[a] = findfa(b);

	}

	else if(father[a]!=-1&&father[b]==-1){

		father[b] = findfa(a);

	}

	else if(father[a]!=-1&&father[b]!=-1){

		father[findfa(a)] = findfa(b);

		father[a] = findfa(b);

	}

}



int main(){

	memset(num,0,sizeof(num));

	memset(father,-1,sizeof(father));

	cin>>n>>m;

	for(int i=1;i<=n;i++)

		cin>>num[i];

	for(int j=0;j<m;j++){

		cin>>a>>b;

		doit(a,b);

	}

	int res = 0;

	for(int i=1;i<=n;i++){

		if(father[i]==-1)

			father[i] = i;

	}

	for(int i=1;i<=n;i++){

		if(findfa(i)- findfa(num[i])==0)

			res++;

	}

	cout<<res<<endl;

}

// Faster C++ solution for the same problem (measured speedup: 1.7525735055582181x):
#include <bits/stdc++.h>



void optimize_cpp_stdio() {

    std::ios::sync_with_stdio(false);

    std::cout.tie(nullptr);

    std::cin.tie(nullptr);

}



int main() {

    optimize_cpp_stdio();

    int n, m;

    std::cin >> n >> m;

    std::vector<int> a(n);

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

        std::cin >> a[i];

        --a[i];

    }

    std::vector<std::vector<int>> G(n);

    for (int i = 0, u, v; i < m; i++) {

        std::cin >> u >> v;

        G[--u].push_back(--v);

        G[v].push_back(u);

    }

    int ans = 0;

    std::vector<bool> vis(n);

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

        if (vis[i]) continue;

        std::vector<int> index, value;

        std::queue<int> q({i});

        vis[i] = true;

        for (; !q.empty(); q.pop()) {

            int u = q.front();

            index.push_back(u);

            value.push_back(a[u]);

            for (int v : G[u]) {

                if (vis[v]) continue;

                vis[v] = true;

                q.push(v);

            }

        }

        std::sort(index.begin(), index.end());

        for (int it : value)

            ans += std::binary_search(index.begin(), index.end(), it);

    }

    std::cout << ans << "\n";

    return 0;

}