pat1067

这题我用了差不多是离散数学里的置换群(其实我也不记得是不是叫置换群,反正这个群里的一些数位置错了,可以通过某个数发起,把这些数换到自己对应的位置)的思想,假如我们找到一个置换群,这个置换群包括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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值