stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include<iostream>

#include<cstdio>

#include<cstring>

#define N 110

using namespace std;

int a[N],dp[N][N][N],n,m;

int main(){

	memset(dp,-128/3,sizeof(dp));

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

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

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

	dp[0][n+1][0]=0;

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

		for(int j=n+1;j>i;j--)

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

				dp[i+1][j][k+1]=max(dp[i+1][j][k+1],dp[i][j][k]+a[i+1]);

				dp[i][j-1][k+1]=max(dp[i][j-1][k+1],dp[i][j][k]+a[j-1]);

				if(a[i+1]<0)

					dp[i+1][j][k+2]=max(dp[i+1][j][k+2],dp[i][j][k]);

				if(a[j-1]<0)

					dp[i][j-1][k+2]=max(dp[i][j-1][k+2],dp[i][j][k]);

			}

	int ans=0;

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

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

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

				ans=max(ans,dp[i][j][k]);

	cout<<ans;

	return 0;

}

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

#include<cstdio>

#include<algorithm>

#define maxn 100

using namespace std;

int n,l,r,a[maxn],p,b[maxn],cnt,sum,ans=0;

int main(){

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

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

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

	for(int i=0;i<=min(n,p);i++){//Ò»¹²½øÐÐÁË¼¸´ÎÈ¡µÄ²Ù×÷ 

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

			int lnum=j,rnum=i-j;

			cnt=0;sum=0;

			for(int k=1;k<=lnum;k++){

				b[++cnt]=a[k];

				sum+=a[k];

			}

			for(int k=n;k>=n-rnum+1;k--){

				b[++cnt]=a[k];

				sum+=a[k];

			}

			sort(b+1,b+cnt+1);

			for(int k=1;k<=min(p-i,cnt);k++){

				if(b[k]>=0)break;

				sum-=b[k];

			}

			ans=max(ans,sum);

		}

	}

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

	return 0;

}

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

#include <cstdio>

#include <cstring>

#include <algorithm>

#define LL long long

using namespace std;

int f[55][105], g[55][105], v[105];

int main(){

    ios::sync_with_stdio(false);

    int n, k; cin>>n>>k;

    for(int i = 1; i <= n; i++) cin>>v[i];

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

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

            f[i][j] = g[i][j] = -1e9;

    }

    f[0][k] = 0;

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

        for(int j = k; j >= 1; j--){

            f[i + 1][j - 1] = max(f[i + 1][j - 1], f[i][j] + v[i + 1]);

            if(j >= 2) f[i + 1][j - 2] = max(f[i + 1][j - 2], f[i][j]);

        }

    }

    g[n + 1][k] = 0;

    for(int i = n + 1; i >= 2; i--){

        for(int j = k; j >= 1; j--){

            g[i - 1][j - 1] = max(g[i - 1][j - 1], g[i][j] + v[i - 1]);

            if(j >= 2) g[i - 1][j - 2] = max(g[i - 1][j - 2], g[i][j]);

        }

    }

    int ans = 0;

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

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

            for(int K = i; K <= k && K <= 2 * i; K++){

                for(int t = n - j + 1; t + K <= k; t++){

                    ans = max(f[i][k - K] + g[j][k - t], ans);

                }

            }

        }

    }

    cout<<ans;

    return 0;

}

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

#include <cstdlib>

#include <vector>

#include <queue>



using namespace std;



int main() {

    int n, k;

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

    // 建立羊肉串

    vector<int> array(n);

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

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

    }



    // 开始枚举

    int maxl = 0;

    for (int a = 0; a <= k; a++) {

        for (int b = 0; b <= k; b++) {

            for (int c = 0; c <= k; c++) {

                if (a+b+c <= k && a+b >= c && a + b <= n) {

                    // 操作合理

                    priority_queue<int> qu;

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

                        qu.push(array[i]);

                    }

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

                        qu.push(array[n - i - 1]);

                    }

                    int sum = 0;

                    for (int i = 0; i < a + b - c; i++) {

                        sum += qu.top();

                        qu.pop();

                    }

                    maxl = max(maxl, sum);

                }

            }

        }



    }

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

    return EXIT_SUCCESS;

 }

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



#define ll long long



const int N = 1e6+3,M=55;



const ll oo=1e18;



int n,m,ans,tc,a[N],b[N],k;



#define f first



#define s second



const int dx[]={0,0,1,-1},

          dy[]={1,-1,0,0};



char s[N];



ll dp[105][105][105];



ll solve(int l,int r,int rem){

    if (rem<0)

        return -1e9;

    if (l>r)

        return 0;

    ll &ret = dp[l][r][rem];

    if (ret!=-oo)

        return ret;

    ret=0;

    ret=max(ret,max(a[l]+solve(l+1,r,rem-1),solve(l+1,r,rem-2)));

    return ret=max(ret,max(a[r]+solve(l,r-1,rem-1),solve(l,r-1,rem-2)));

}



int main(){

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

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

            for(int k=0;k<105;k++)

                dp[i][j][k]=-oo;

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

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

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

    printf("%lld",solve(0,n-1,k));

}






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

#include<cstdio>

#include<cstdlib>

#include<cmath>

#include<cstring>

#include<algorithm>

#include<queue>

#define LL long long

#define inl inline

#define re register

#define MAXN 10100

using namespace std;

int n,k;

int v[54];

int ans;int g[55];

int work(int l,int r)

{

	int cnt=k;

	if(l+r>k)return 0;

	int ind=0;

	for(int i=1;i<=l;i++)g[++ind]=v[i];

	for(int i=n;i>=n-r+1;i--)g[++ind]=v[i];

	sort(g+1,g+ind+1);

	cnt-=ind;

	int t=1;

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

	{

		if(g[i]<0&&cnt>0)

			cnt--,t++;

	}

	int tmp=0;

	for(;t<=ind;t++)tmp+=g[t];

	return tmp;

}

int main()

{

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

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

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

		for(int r=0;r<=n-l;r++)

		{

			ans=max(ans,work(l,r));

		}

	cout<<ans;

	return 0;

}




// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

#define all(v) ((v).begin()),((v).end())

#define ll long long

#define fastIO cout << fixed << setprecision(12), ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)

double const EPS = 1e-12, PI = acos(-1);

const int N = 2e5 + 9, M = 3e3 + 9, OO = 1e9 + 7, MOD = 1e9 + 7;

const ll inf = 1e18;



ll mem[109][109][109], arr[N];

int n, m;



ll solve(int l, int r, int steps) {

  if(steps < 0)

    return -inf;

  if(steps == 0 || l > r)

    return 0;

  ll& ret = mem[l][r][steps];

  if(~ret)

    return ret;

  ret = -inf;

  ll c1 = solve(l + 1, r, steps - 1) + arr[l];

  ll c2 = solve(l, r - 1, steps - 1) + arr[r];

  ll c3 = solve(l + 1, r, steps - 2);

  ll c4 = solve(l, r - 1, steps - 2);

  ret = max(max(c1, c2), max(c3, c4));

  return ret;

}



int main() {

  fastIO;

#ifdef LOCAL

  freopen("input.in", "rt", stdin);

#endif

  cin >> n >> m;

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

    cin >> arr[i];

  }

  memset(mem, -1, sizeof mem);

  ll best = -inf;

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

    best = max(best, solve(0, n - 1, i));

  }

  cout << best;

  return 0;

}


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

#include<vector>

#include<algorithm>

using namespace std;

 

const int maxn = 55;

int A[maxn], sum[maxn]={0};

int n,k;//n块羊肉   k次操作 

vector<int> vt;



int main(){

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

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

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

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

		sum[i] += A[i];//0~i累积的和 

	}

	int r = min(n,k);

	int MAX = 0;

	for(int x=0;x<=r;x++){

		for(int y=0;x+y<=r;y++){

			int remain = min(k-x-y,x+y);//放回去的次数

			vt.clear();

			int sum = 0;

			for(int i=0;i<x;i++){//左边x个

				vt.push_back(A[i]);

				sum += A[i];

			} 

			for(int j=0,i=n-1;j<y;j++,i--){//右边y个

				vt.push_back(A[i]);

				sum += A[i];

			}

			sort(vt.begin(),vt.end());

			for(int j=0;j<remain;j++){//放回去 

				if(vt[j]<0){

					sum -= vt[j];

				}else{

					break;

				}

			}

			MAX = max(MAX,sum); 

		}

	} 

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

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define rep(i, n) for(int i = 0; i < (n); i++)

#define rep1(i, n) for(int i = 1; i <= (n); i++)

#define co(x) cout << (x) << "\n"

#define cosp(x) cout << (x) << " "

#define ce(x) cerr << (x) << "\n"

#define cesp(x) cerr << (x) << " "

#define pb push_back

#define mp make_pair

#define Would

#define you

#define please



const int cm = 1 << 17;

char cn[cm], * ci = cn + cm, ct;

inline char getcha() {

	if (ci - cn == cm) { fread_unlocked(cn, 1, cm, stdin); ci = cn; }

	return *ci++;

}

inline int getint() {

	int A = 0;

	if (ci - cn + 16 > cm) while ((ct = getcha()) >= '0') A = A * 10 + ct - '0';

	else while ((ct = *ci++) >= '0') A = A * 10 + ct - '0';

	return A;

}



int P[100001];

int Find(int A) {

	if (P[A] < 0) return A;

	return P[A] = Find(P[A]);

}



bool Unite(int A, int B) {

	int a = Find(A);

	int b = Find(B);

	if (a == b) return false;

	if (P[a] > P[b]) swap(a, b);

	P[a] += P[b];

	P[b] = a;

	return true;

}



int main() {

	cin.tie(0);

	ios::sync_with_stdio(false);





	int N = getint(), M = getint();

	int ip[100001];

	rep1(i, N) ip[getint()] = i;



	rep1(i, N) P[i] = -1;

	rep(i, M) Unite(getint(), getint());



	int kotae = 0;

	rep1(i, N) kotae += Find(i) == Find(ip[i]);



	co(kotae);



	Would you please return 0;

}

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

#include<cstdio>

#include<algorithm>

using namespace std;

typedef long long ll;

#define rep(i, n) for(int i = 0; i < (n); i++)

#define rep1(i, n) for(int i = 1; i <= (n); i++)

#define co(x) cout << (x) << "\n"

#define cosp(x) cout << (x) << " "

#define ce(x) cerr << (x) << "\n"

#define cesp(x) cerr << (x) << " "

#define pb push_back

#define mp make_pair

#define Would

#define you

#define please



const int cm = 1 << 17;

char cn[cm], * ci = cn + cm;

inline char getcha() {

	if (ci - cn == cm) { fread(cn, 1, cm, stdin); ci = cn; }

	return *ci++;

}

inline int getint() {

	char C = getcha();

	int A = C - '0';

	while ((C = getcha()) >= '0') A = A * 10 + C - '0';

	return A;

}



int P[100001];

int Find(int A) {

	if (P[A] < 0) return A;

	return P[A] = Find(P[A]);

}



int main() {

	//cin.tie(0);

	//ios::sync_with_stdio(false);





	int N = getint(), M = getint();

	int p[100001];

	rep1(i, N) p[i] = getint();



	rep1(i, N) P[i] = -1;

	rep(i, M) {

		int a = Find(getint());

		int b = Find(getint());

		if (a == b) continue;

		if (P[a] > P[b]) swap(a, b);

		P[a] += P[b];

		P[b] = a;

	}



	int kotae = 0;

	rep1(i, N) kotae += Find(i) == Find(p[i]);



	printf("%d", kotae);



	Would you please return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include "bits/stdc++.h"

using namespace std;



//



#define RESIDUE(u,v) (capacity[u][v] - flow[u][v])

#define RCOST(u,v) (cost[u][v] + h[u] - h[v])

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n)   FOR(i,0,n)

#define LL long long



int p[100001];

int ind[100001];



#define N 100001



int par[N];

int rnk[N];



void init_uf(){

  REP(i,N){

    par[i]=i;

    rnk[i]=0;

  }

}



int find(int x){

  if(par[x] == x)

    return x;

  else

    return find(par[x]);

}



void unite(int x,int y){

  x=find(x);

  y=find(y);

  if(x==y)

    return;

      

  if(rnk[x] < rnk[y])

    par[x] = y;

  else{

    par[y] = x;

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

  }

}



bool same(int x,int y){

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

}



int main(){

  int n,m;

  cin>>n>>m;

  REP(i,n){

    cin>>p[i+1];

    ind[p[i+1]]=i+1;

  }



  init_uf();

  int dum1,dum2;

  REP(i,m){

    cin>>dum1>>dum2;

    unite(ind[dum1],ind[dum2]);

  }



  int ret = 0;

  REP(i,n){

    if(same(i+1,ind[i+1])) ret++;

  }

  cout<<ret<<endl;

  return 0;

}


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

using namespace std;



#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n)   FOR(i,0,n)

#define LL long long



class UnionFind{

private:

  std::vector<int> par;

  std::vector<int> rnk;

public:

  UnionFind(int n):par(n),rnk(n){

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

      par[i]=i;

      rnk[i]=0;

    }

  }

  

  int find(int x){

    if(par[x] == x)

      return x;

    else

      return find(par[x]);

  }



  void unite(int x,int y){

    x=find(x);

    y=find(y);

    if(x==y)

      return;

      

    if(rnk[x] < rnk[y])

      par[x] = y;

    else{

      par[y] = x;

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

    }

  }



  bool same(int x,int y){

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

  }

};



int n,m;



int main(){

  cin>>n>>m;

  int tmp,tmp2;

  UnionFind un(2*n);

  REP(i,n){

    cin>>tmp;

    un.unite(i,n+tmp-1);

  }

  REP(i,m){

    cin>>tmp>>tmp2;

    un.unite(tmp-1,tmp2-1);

  }

  LL ret=0;

  REP(i,n)ret+=(un.same(i,n+i))?1:0;

  cout<<ret<<endl;

  return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



#define inf 1<<30

#define pqueue priority_queue

#define mp make_pair

#define pb push_back

#define fn fill_n

typedef long long llong;

typedef unsigned long long ullong;

typedef pair<int, int> P;

struct UnionFind{

	int par[100001];



	UnionFind(){};

	UnionFind(int n){

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

			par[i] = i;

	};

	int find(int n){

		if(par[n] == n) return n;

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

	};

	bool isSame(int a, int b){

		return find(a) == find(b);

	};

	void marge(int a, int b){

		a = find(a);

		b = find(b);

		if(a == b) return;

		else if(a < b)

			par[b] = a;

		else

			par[a] = b;

		return;

	};

};



int N, M;

int id[100001] = {};

UnionFind uf(100001);



int main(){

	cin >> N >> M;

	int in;

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

		cin >> in;

		id[in] = i;

	}

	int a, b;

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

		cin >> a >> b;

		uf.marge(a,b);

	}

	int cnt = 0;

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

		if(uf.isSame(i, id[i]))

			cnt++;



	cout << cnt << endl;



	return 0;

}

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



using namespace std;



#define inf 1<<30

#define pqueue priority_queue

#define mp make_pair

#define pb push_back

#define fn fill_n

typedef long long llong;

typedef unsigned long long ullong;

typedef pair<int, int> P;

struct UnionFind{

	vector<int> par, rank;



	UnionFind(){};

	UnionFind(int n){

		par.resize(n), rank.resize(n);

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

			par[i] = i, rank[i] = 0;

	};

	int find(int n){

		if(par[n] == n) return n;

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

	};

	bool isSame(int a, int b){

		return find(a) == find(b);

	};

	void marge(int a, int b){

		a = find(a);

		b = find(b);

		if(a == b) return;

		if(rank[a] < rank[b]) swap(a,b);

		if(rank[a] == rank[b]) rank[a]++;

		par[b] = a;

		return;

	};

};



int N, M;

int id[100001] = {};

UnionFind uf;



int main(){

	cin >> N >> M;

	uf = UnionFind(N+1);

	int in;

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

		cin >> in;

		id[in] = i;

	}

	int a, b;

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

		cin >> a >> b;

		uf.marge(a,b);

	}

	int cnt = 0;

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

		if(uf.isSame(i, id[i]))

			cnt++;



	cout << cnt << endl;



	return 0;

}

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

using namespace std;

typedef long long ll;

#define NODE_MAX 100001

int par[NODE_MAX],rk[NODE_MAX];

void init(){

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

    par[i]=i;

    rk[i]=0;

  }

}

int root(int x){

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

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

}

void unite(int x,int y){

  x = root(x);

  y = root(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 root(x)==root(y);

}

int main(){

  ll n,m,cnt=0;

  cin >> n >> m;

  init();

  ll p[n],x[m],y[m];

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

    cin >> p[i];

  }

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

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

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

  }

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

    if(same(i+1,p[i])){

      cnt++;

    }

  }

  cout << cnt << endl;

}


// Optimized solution to the same problem (faster):
// I SELL YOU...! 

#include<iostream>

#include<vector>

#include<algorithm>

#include<functional>

#include<queue>

#include<chrono>

#include<iomanip>

#include<map>

#include<set>

using namespace std;

using ll = long long;

using P = pair<ll,ll>;

using TP = tuple<ll,ll,ll>;

void init_io(){

  cin.tie(0);

  ios::sync_with_stdio(false);

  cout << setprecision(18);

}

class union_find{

  int n;

  vector<int> par,rk,size;

  public:

  union_find(int max_n){

    n = max_n+1;

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

      par.emplace_back(i);

      rk.emplace_back(0);

      size.emplace_back(1);

    }

  }

  int root(int x){

    vector<int> nodes;

    while(x!=par[x]){

      nodes.emplace_back(x);

      x = par[x];

    }

    for(auto v:nodes){

      par[v] = x;

    }

    return x;

  }

  void unite(int x,int y){

    x = root(x);

    y = root(y);

    if(x==y) return;

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

      par[x] = y;

      size[y] += size[x];

    }else{

      par[y] = x;

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

      size[x] += size[y];

    }

  }

  bool same(int x,int y){

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

  }

  int treesize(int x){

    return size[root(x)];

  }

};

signed main(){

  init_io();

  ll n,m,ans=0;

  cin >> n >> m;

  union_find uf(n);

  vector<ll> p(n),x(m),y(m);

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

    cin >> p[i];

    p[i]--;

  }

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

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

    x[i]--;

    y[i]--;

    uf.unite(x[i],y[i]);

  }

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

    if(uf.same(p[i],i)){

      ans++;

    }

  }

  cout << ans << endl;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

//#pragma GCC optimize("O3")

//#pragma GCC target ("sse4")

using namespace std;

#define PB push_back

#define all(x) (x).begin(),(x).end()

#define MEM(x,a) memset((x),a,sizeof((x)))

#define F first

#define S second

#define imx INT_MAX

#define inI(x) scanf("%d",&x)

#define inI2(x,y) scanf("%d %d",&x,&y)

#define inI3(x,y,z) scanf("%d %d %d",&x,&y,&z)

const long long MOD = (long long)(1e9+7);

const long long MMX = (long long)(1e18);

typedef long long LL;

vector<int>v[100005];

int n,m,num[100005],gr[100005],x,y,k,ans;

bitset<100005>go;

queue<int>q;

int main()

{

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

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

    {

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

    }

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

    {

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

        v[x].push_back(y);

        v[y].push_back(x);

    }

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

    {

        if(!go[i])

        {

            q.push(i);

            while(!q.empty())

            {

                k=q.front();

                go[k]=true;

                gr[k]=i;

                q.pop();

                for(int j=0;j<v[k].size();j++)

                {

                    if(!go[v[k][j]])

                    {

                        q.push(v[k][j]);

                    }

                }

            }

        }

    }

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

    {

        if(gr[i]==gr[num[i]])ans++;

    }

    printf("%d",ans);

}


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

using namespace std;



int p[100100];

int li[100100];

map<int,int> mp;



int fi(int nw)

{

	if(li[nw]==nw)return nw;

	return li[nw]=fi(li[nw]);

}



void uni(int l1,int l2)

{

	li[l1]=l2;

}



main()

{

	int n,m;

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

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

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

	{

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

		mp[p[i]]=i;

	}

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

	{

		int a,b;

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

		if(fi(a)!=fi(b))

		{

			uni(fi(a),fi(b));

		}

	}

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

	int ans=0;

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

	{

		if(li[mp[i]]==li[i])

		{

			ans++;

		}

	}

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

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
/*

 * ARC097_D.cpp

 *

 *  Created on: May 12, 2018

 *      Author: 13743

 */



#include<iostream>

#include<vector>

#include<algorithm>

#include<queue>

#include<stack>

#include<unordered_set>



using namespace std;



vector<int> adj[100001];

int p[100001];

vector<vector<int>> comps;

int vis[100001];







void connected(int rt, int i) {

	if(vis[rt]) return;

	vis[rt] = i;

	comps[i].push_back(rt);

	for(int j=0; j<adj[rt].size(); j++) {

		connected(adj[rt][j], i);

	}

}



int main() {

	comps.resize(100000);

	int n, m;

	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;

		adj[x].push_back(y);

		adj[y].push_back(x);

	}



	int n2 = 1;

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

		if(vis[i] == 0) {

			connected(i, n2);

			n2++;

		}

	}

	int sumS = 0;

	for(int i=0; i<comps.size(); i++) {

		

		for(int j=0; j<comps[i].size(); j++) {

			if(vis[p[comps[i][j]]] == vis[comps[i][j]]) {sumS++;}

		}

	}



	cout << sumS << endl;

}






// Optimized solution to the same problem (faster):
/*

 * ARC097_D.cpp

 *

 *  Created on: May 14, 2018

 *      Author: 13743

 */



#include<iostream>

#include<algorithm>

#include<vector>

#include<stack>

#include<queue>

#include<string>

using namespace std;

typedef long long llong;



#define PB push_back

#define SZ(a) int((a).size())

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

#define FOR(i,a,b) for(int i=(a); i<(b); ++i)

#define REP(i,n) FOR(i,0,n)

#define UNIQUE(a) a.erase(unique(ALL(a)), a.end())



int seqP[100001];

vector<int> adjL[100001];

int comps[100001];



void connected(int v, int num) {

	if(comps[v] > 0) return;

	comps[v] = num;

	REP(i, SZ(adjL[v])) {

		connected(adjL[v][i], num);

	}

}



int main() {

	cin.tie(0);

	ios::sync_with_stdio(false);



	int N, M;

	cin >> N >> M;

	REP(i, N) {

		cin >> seqP[i+1];

	}

	REP(i, M){

		int u, v;

		cin >> u >> v;

		adjL[u].PB(v);

		adjL[v].PB(u);

	}



	int numC = 1;

	FOR(i, 1, N+1) {

		if(comps[i] > 0) continue;

		connected(i, numC);

		++numC;;

	}



	int ans = 0;

	FOR(i, 1, N+1) {

		if(comps[seqP[i]] == comps[i]) {

			++ans;

		}

	}



	cout << ans << endl;

}






// Fastest known solution for this problem: