题意:就是给定一个排列,问最少交换次数,使得该排列没有 fixed point。
分析:记录是 fixed point的元素,该元素总数为cnt,如果cnt是1的话,那么只要交换一次,然后从剩下的随便找个数和这个元素交换就可以。如果cnt>1,分2种,如果是偶数,交换次数就是cnt/2,交换方法就是相邻两个两两交换就可以了;如果是奇数,那么交换次数就是cnt/2 +1,先把前面cnt-1个元素两两交换,最后一个和前面的任意一个随便交换就可以了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAX_N 200010
using namespace std;
int main(void)
{
int n;
int a[MAX_N];
int b[MAX_N];
while(scanf("%d",&n)==1)
{
int cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==i)
b[cnt++]=i;
}
printf("%d\n",cnt%2==1?(cnt/2)+1:cnt/2);
if(cnt==1)
{
for(int i=1;i<=n;i++)
{
if(a[i]!=b[0])
{
printf("%d %d\n",a[i],b[0]);
break;
}
}
continue;
}
if(cnt%2==0)
{
for(int i=0;i<cnt-1;i+=2)
printf("%d %d\n",b[i],b[i+1]);
}
else
{
for(int i=0;i<cnt-2;i+=2)
printf("%d %d\n",b[i],b[i+1]);
printf("%d %d\n",b[cnt-2],b[cnt-1]);
}
}
return 0;
}