stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#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 ;

}

// Optimized solution to the same problem (faster):
#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 ;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#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);

    }

}


// Optimized solution to the same problem (faster):
#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;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}

// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#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;

}


// Optimized solution to the same problem (faster):
#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;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <cstdio>

#include <cstring>

#include <iostream>

#include <string>

#include <cmath>

#include <bitset>

#include <vector>

#include <map>

#include <set>

#include <queue>

#include <deque>

#include <algorithm>

#include <complex>

#include <unordered_map>

#include <random>

using namespace std;

typedef long long int ll;

typedef pair<int, int> P;

vector<int> g[100000];

int  used[100000];

int used2[100000];

int p[100000];

int c;

void dfs(int x){

    used[x]=c;

    used2[p[x]]=c;

    for(auto y:g[x]){

        if(!used[y]) dfs(y);

    }

}

int main()

{

	int n, m;

	cin>>n>>m;

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

        cin>>p[i]; p[i]--;

    }

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

        int x, y;

        cin>>x>>y;

        x--; y--;

        g[x].push_back(y);

        g[y].push_back(x);

    }

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

        if(used[i]) continue;

        c++;

        dfs(i);

    }

    int ans=0;

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

        if(used[i]==used2[i]) ans++;

    }

    cout<<ans<<endl;

	return 0;

}

// Optimized solution to the same problem (faster):
#include <cstdio>

#include <cstring>

#include <iostream>

#include <string>

#include <cmath>

#include <bitset>

#include <vector>

#include <map>

#include <set>

#include <queue>

#include <deque>

#include <algorithm>

#include <complex>

#include <unordered_map>

#include <random>

using namespace std;

typedef long long int ll;

typedef pair<int, int> P;

int par[100002];

int rk[100002];

int p[100000];

void init(int n){

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

		par[i]=i;

	}

}



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(rk[x]<rk[y]){

		par[x]=y;

	}else{

		par[y]=x;

		if(rk[x]==rk[y]) rk[x]++;

	}

}

 

bool same(int x, int y){

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

}

int main()

{

	int n, m;

	cin>>n>>m;

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

        cin>>p[i]; p[i]--;

    }

    init(n);

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

        int x, y;

        cin>>x>>y;

        x--; y--;

        unite(x, y);

    }

    int p2[100000];

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

        p2[p[i]]=find(i);

    }

    int ans=0;

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

        if(p2[i]==find(i)) ans++;

    }

    cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <iostream>

#include <array>



std::array<int, 100005> p;

std::array<int, 100005> fa;



int find(int x){return fa[x]^x?fa[x]=find(fa[x]):x;}



int main()

{

    int n, m;

    std::cin >> n >> m;

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

    {

        int temp;

        std::cin >> temp;

        p[i] = temp;

        fa[i] = i;

    }



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

    {

        int u, v;

        std::cin >> u >> v;



        fa[find(u)] = find(v);

    }



    int count = 0;

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

    {

        if (find(p[i - 1]) == find(i))

        {

            count++;

        }

    }

    std::cout << count << std::endl;

}


// Optimized solution to the same problem (faster):
#include <cstdio>

#include <array>



std::array<int, 100005> p;

std::array<int, 100005> fa;



int find(int x)

{

    if (fa[x] != x)

    {

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

        return fa[x];

    }

    else

    {

        return x;

    }

}



int main()

{

    int n, m;

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

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

    {

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

        fa[i] = i;

    }

    int u, v;

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

    {

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

        fa[find(u)] = find(v);

    }



    int count = 0;

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

    {

        if (find(p[i - 1]) == find(i))

        {

            count++;

        }

    }

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

}


// Fastest known solution for this problem: