地址:https://pintia.cn/problem-sets/994805342720868352/problems/994805403651522560
最优的策略就是,0属于哪一位,就和哪个数字交换,这样是最优的;
那么就会形成一个环,像3 5 7 2 6 4 9 0 8 1;下标是0 1 2 3 4 5 6 7 8 9;
所以第一个环0 -> 7 -> 2 -> 3 -> 0,需要交换环内数num - 1;
第二个环0 -> 5 -> 1 -> 9 -> 6- > 4 -> 5,需要交换环内数num + 1;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int MAXN = 1e5 + 5;
int a[MAXN];
int b[MAXN];
int num[MAXN];
int Find(int x)
{
if(x == b[x])
return x;
return b[x] = Find(b[x]);
}
void join(int x,int y)
{
int p = Find(x);
int q = Find(y);
if(p != q){
b[p] = q;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 0;i < n;++i){
scanf("%d",&a[i]);
b[i] = i;
}
for(int i = 0;i < n;++i){
join(i,a[i]);
}
memset(num,0,sizeof(num));
for(int i = 0;i < n;++i){
num[Find(i)]++;
}
int x = num[Find(0)];
int y = Find(0);
int ans = 0;
if(x != 1)
ans = x - 1;
for(int i = 0;i < n;++i){
if(num[i] == 1 || i == y || num[i] == 0)
continue;
ans = ans + num[i] + 1;
}
printf("%d\n",ans);
return 0;
}