这题我用了差不多是离散数学里的置换群(其实我也不记得是不是叫置换群,反正这个群里的一些数位置错了,可以通过某个数发起,把这些数换到自己对应的位置)的思想,假如我们找到一个置换群,这个置换群包括0,那么置换群里有多少个数(包括0)我们就换多少次就好了,假如没有0,那么我们先要把0加入到这个置换群(就是置换群中的某个数和0换一个位置)继续刚才的做法。至于做法总数的话,我现在假设0就在0这个位置,那么每次换,我都得把0加入一个置换群,次数就是需要换的数加上置换群的个数,但是0要是不在0这个位置呢?那么我们可以减少2步,第一我们不需要把0加入一个置换群中,因为0已经属于一个置换群了。第二加入后置换群中的数的个数多了1,步数也多算了一次,所以把这2步减掉就好了。代码如下:
#include<stdio.h>
int a[100001];
int mark[100001];
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF)
{
int cnt=0;
int flag=0;
int ans=0;
for(i=0;i<n;i++)
{
scanf("%d",a+i);
mark[i]=0;
if(a[i]!=i)
cnt++;
else
{
mark[i]=1;
if(i==0)
flag=1;
}
}
for(i=0;i<n;i++)
{
if(mark[i]==0)
{
int tmp=i;
mark[i]=0;
while(a[tmp]!=i)
{
mark[a[tmp]]=1;
tmp=a[tmp];
}
ans++;
}
}
ans=ans+cnt;
if(flag==0)
ans-=2;
printf("%d\n",ans);
}
return 0;
}